Compare commits

...

70 Commits

Author SHA1 Message Date
Jakob Borg
516f3e29e8 chore(proto): change symlinktarget to be byte sequence (fixes #9913) (#9914) 2025-01-11 17:38:29 +01:00
Jakob Borg
ab20c16982 fix(api): don't crash requests after failing to unmarshal tokens (fixes #9909) (#9912)
Unclear why this would happen, but apparently it does?
2025-01-09 21:47:10 +01:00
Jakob Borg
0c1df81ee9 fix(scanner): don't warn when legitimately skipping a directory (#9911)
Such as ignored directories etc.
2025-01-09 18:42:18 +00:00
Jakob Borg
d324b2ac86 fix(db): correct unsafe RLock order (fixes #9906) (#9910)
Marshal() was called with the read lock held, and in turn called
Created() which also takes the read lock. This is fine by itself, but
there is a risk of deadlock if another call to lock the mutex happens
concurrently, as the lock call will block the inner rlock and the outer
rlock can never become unlocked.

It's an easy fix as marshalling is guaranteed to be called with a read
lock and does not need to call any methods that read lock themselves.
2025-01-09 19:33:04 +01:00
Jakob Borg
0231089b99 fix(db): add JSON tags to types used in API returns (fixes #9907) (#9908)
These types are also used in the API, and hence need JSON tags.
2025-01-09 09:26:34 +00:00
Jakob Borg
74ffb85467 fix(model): correct type of fileInfoType in API browse response (fixes #9904) (#9905)
This was broken in the Protobuf refactor. The reason is that with the
previous library, generated types would have a JSON marshalling method
that would automatically return strings for enums. In the current
library you need to use the jsonpb marshaller for that, but these are
hand crafted structs so we can't do that. The easy solution is to just
use strings directly, since this is an API-only type anyway.
2025-01-08 11:08:33 +01:00
Syncthing Release Automation
dcd280e6e2 chore(gui, man, authors): update docs, translations, and contributors 2025-01-06 03:47:27 +00:00
Jakob Borg
4e56dbd883 build(deps): update dependencies (#9900) 2025-01-01 19:49:52 +00:00
Syncthing Release Automation
13d7881b80 chore(gui, man, authors): update docs, translations, and contributors 2024-12-30 03:46:20 +00:00
Simon Frei
1d2c53bf3c chore(scanner): avoid scan failures and report if they happen (#9888) 2024-12-28 17:09:38 +01:00
Syncthing Release Automation
9c449c966b chore(gui, man, authors): update docs, translations, and contributors 2024-12-23 03:46:12 +00:00
Jakob Borg
ec2d4638e3 build: fix publish-nightly tools checkout 2024-12-22 09:02:11 +01:00
André Colomb
0ce92befc8 chore(gui): fix merge conflict on Weblate (#9882)
Commit dee920a840 was merged into
Weblate's repository, but later replaced on main by
2167ce9656. This led to a merge conflict,
which this commit fixes cleanly. After merging, we can unlock Weblate
again.
2024-12-21 21:54:17 +00:00
Jakob Borg
2167ce9656 build: reinstate docker push for main 2024-12-21 16:17:21 +01:00
Jakob Borg
0dc85d74aa build: also push to ghcr.io 2024-12-21 15:43:49 +01:00
Jakob Borg
b6e3f8037b build: workaround for tag builds
The GitHub checkout action does weird stuff with tags which breaks `git
describe`. This works around that so we get proper release builds on tag
pushes.
2024-12-21 14:35:04 +01:00
Jakob Borg
00e7161a8f build: compat.json should be in the signed packages bundle 2024-12-20 10:34:29 +01:00
Jakob Borg
b5a7879eca fix(stdiscosrv): handle announcements properly :p (#9881)
Further protobuf refactor damage, also adding some better debugging
2024-12-19 20:43:46 +00:00
Jakob Borg
4355dc69ea fix(discovery): properly unmarshal local discovery (#9880)
Damage from recent protobuf refactoring
2024-12-19 20:16:44 +00:00
Jakob Borg
371ba69447 build: slightly streamline build dependencies 2024-12-19 15:08:17 +01:00
Jakob Borg
79ef57d0ea fix(scanner): continue walk after special files (fixes #9872) (#9877)
We must skip unix sockets, fifos, etc when scanning as these are not
filetypes we can handle. Currently we return a "bug" error, which
results in the walk being aborted and the rest of the tree being
essentially invisible to Syncthing. Instead, just ignore these files and
continue onwards.

This might well be #9859 as well but I can't confirm.
2024-12-19 08:27:53 +01:00
Jakob Borg
8bd6bdd397 chore(model): clarify log message (fixes #9875) (#9876) 2024-12-18 07:56:06 +00:00
Simon Frei
ce3248cea7 chore(fs): add debug logging for case cache registry (#9869)
Clearly something is up with it, but I still have no clue what. This
might give some clue when affected user enable debug logging.
2024-12-16 12:04:24 +01:00
Jakob Borg
99a6f3a5b6 docs: update section on code signing 2024-12-16 11:42:34 +01:00
Jakob Borg
c2e10dc156 build: skip Docker push for main, reserve for release 2024-12-16 11:39:13 +01:00
Jakob Borg
fc914f3237 build: sign asc files using ezapt
And same keys as APT archive
2024-12-16 11:35:41 +01:00
Jakob Borg
811d3752d0 build: loki vars are in secrets 2024-12-16 09:26:21 +01:00
Jakob Borg
00827dd5c1 build: consolidate release environment for actions
signing & docker -> release
2024-12-16 08:57:35 +01:00
Syncthing Release Automation
a981c21d27 chore(gui, man, authors): update docs, translations, and contributors 2024-12-16 03:50:41 +00:00
Jakob Borg
163dc122f3 build: update compat.yaml for Go 1.24 (rc1) (fixes #9870) 2024-12-15 11:09:14 +01:00
Jakob Borg
83727e0824 build(deps): update dependencies (#9866) 2024-12-10 14:33:47 +01:00
Jakob Borg
529d3ef764 ci: reduce frequency of dependabot nags 2024-12-10 09:53:46 +01:00
Jakob Borg
fefbf4dcc8 build: run release flows on tag pushes 2024-12-09 08:32:15 +01:00
André Colomb
b9c6d3ae09 fix(config): skip GUI port probing for UNIX sockets (fixes #9855) (#9858)
When creating an initial default config, we usually probe for a free
TCP port.  But when a UNIX socket is specified via the `STGUIADDRESS=`
override or the `--gui-address=unix:///...` command line syntax, parsing
that option will fail during port probing.

The solution is to just skip the port probing when the address is
determined to specify something other than a TCP socket.

### Testing

Start with a fresh home directory each time.
1. Specify a UNIX socket for the GUI (works with this PR):

TMPHOME=$(mktemp -d); ./syncthing --home=$TMPHOME
--gui-address=unix://$TMPHOME/socket

2. Specify no GUI address (probes for a free port if default is taken,
   as before):

       TMPHOME=$(mktemp -d); ./syncthing --home=$TMPHOME

3. Specify a TCP GUI address (probes whether the given port is taken,
   as before):

TMPHOME=$(mktemp -d); ./syncthing --home=$TMPHOME
--gui-address=127.0.0.1:8385
2024-12-09 07:24:42 +00:00
Syncthing Release Automation
7bea8c758a chore(gui, man, authors): update docs, translations, and contributors 2024-12-09 03:50:45 +00:00
Alex Ionescu
479c0d3f16 fix(gui): reflect folder password visibility by changing button icon (#9857)
Make the "toggle password visibility" button on encrypted
folders change its icon from `fa-eye` to `fa-eye-slash` while the
password is visible.
2024-12-08 21:20:31 +01:00
Jakob Borg
d9ce7c3166 build: build all the things (#9845)
Build packages for stdiscosrv and strelaysrv as well.
2024-12-05 10:09:33 -05:00
Jakob Borg
69979996d9 build(infra): also push Docker images to ghcr.io 2024-12-03 07:54:06 -05:00
Jakob Borg
da58e5c50c build(deps): update dependencies (#9852) 2024-12-03 12:48:10 +00:00
Syncthing Release Automation
44e259142f chore(gui, man, authors): update docs, translations, and contributors 2024-12-02 03:50:30 +00:00
Jakob Borg
77970d5113 refactor: use modern Protobuf encoder (#9817)
At a high level, this is what I've done and why:

- I'm moving the protobuf generation for the `protocol`, `discovery` and
`db` packages to the modern alternatives, and using `buf` to generate
because it's nice and simple.
- After trying various approaches on how to integrate the new types with
the existing code, I opted for splitting off our own data model types
from the on-the-wire generated types. This means we can have a
`FileInfo` type with nicer ergonomics and lots of methods, while the
protobuf generated type stays clean and close to the wire protocol. It
does mean copying between the two when required, which certainly adds a
small amount of inefficiency. If we want to walk this back in the future
and use the raw generated type throughout, that's possible, this however
makes the refactor smaller (!) as it doesn't change everything about the
type for everyone at the same time.
- I have simply removed in cold blood a significant number of old
database migrations. These depended on previous generations of generated
messages of various kinds and were annoying to support in the new
fashion. The oldest supported database version now is the one from
Syncthing 1.9.0 from Sep 7, 2020.
- I changed config structs to be regular manually defined structs.

For the sake of discussion, some things I tried that turned out not to
work...

### Embedding / wrapping

Embedding the protobuf generated structs in our existing types as a data
container and keeping our methods and stuff:

```
package protocol

type FileInfo struct {
  *generated.FileInfo
}
```

This generates a lot of problems because the internal shape of the
generated struct is quite different (different names, different types,
more pointers), because initializing it doesn't work like you'd expect
(i.e., you end up with an embedded nil pointer and a panic), and because
the types of child types don't get wrapped. That is, even if we also
have a similar wrapper around a `Vector`, that's not the type you get
when accessing `someFileInfo.Version`, you get the `*generated.Vector`
that doesn't have methods, etc.

### Aliasing

```
package protocol

type FileInfo = generated.FileInfo
```

Doesn't help because you can't attach methods to it, plus all the above.

### Generating the types into the target package like we do now and
attaching methods

This fails because of the different shape of the generated type (as in
the embedding case above) plus the generated struct already has a bunch
of methods that we can't necessarily override properly (like `String()`
and a bunch of getters).

### Methods to functions

I considered just moving all the methods we attach to functions in a
specific package, so that for example

```
package protocol

func (f FileInfo) Equal(other FileInfo) bool
```

would become

```
package fileinfos

func Equal(a, b *generated.FileInfo) bool
```

and this would mostly work, but becomes quite verbose and cumbersome,
and somewhat limits discoverability (you can't see what methods are
available on the type in auto completions, etc). In the end I did this
in some cases, like in the database layer where a lot of things like
`func (fv *FileVersion) IsEmpty() bool` becomes `func fvIsEmpty(fv
*generated.FileVersion)` because they were anyway just internal methods.

Fixes #8247
2024-12-01 16:50:17 +01:00
André Colomb
2b8ee4c7a5 chore(gui): cache input type in each advanced settings category (#9802)
Each section in the advanced settings dialog has similar code to insert
repeated input fields for each option. But only the first section (GUI
options) was adjusted in #9743 to avoid calling the `inputTypeFor()`
function repeatedly.

Apply the same caching to a locally scoped variable for each ng-repeat
entry by defining it in an ng-init directive.
2024-12-01 12:30:05 +00:00
bt90
be952e5f2d chore(config): add Chinese STUN servers (#9843) 2024-11-30 08:33:55 +01:00
Jakob Borg
43ebac4242 fix(model): create fileset under lock (#9840)
I came accross this in another context and didn't investigate fully, but
literally ten lines above this code, in another method, we say that
filesets _must_ be created under the lock. It's either one or the other
and I'm taking the safer route here.

---------

Co-authored-by: Simon Frei <freisim93@gmail.com>
2024-11-28 13:41:44 +00:00
Jakob Borg
f08a0ed01c build(deps): update dependencies (#9833) 2024-11-25 07:25:24 +00:00
Jakob Borg
612fdff377 build: automatically update APT repository on release
This uses https://github.com/kastelo/ezapt to generate and sign the
archive, and uploads it to blob storage.
2024-11-24 22:55:12 +01:00
Jakob Borg
8ccb7f1924 fix(protocol): allow encrypted-to-encrypted connections again
Encrypted-to-encrypted connections (i.e., ones where both sides set a
password) used to work but were broken in the 1.28.0 release. The
culprit is the 5342bec1b refactor which slightly changed how the request
was constructed, resulting in a bad block hash field.

Co-authored-by: Simon Frei <freisim93@gmail.com>
2024-11-24 22:55:12 +01:00
André Colomb
65d0ca8aa9 fix(config): respect GUI address override in fresh default config (fixes #9783) (#9675)
### Purpose

When generating a new `config.xml` file with default options, the GUI
address is populated with a hard-coded default value of
`127.0.0.1:8384`, except for a random free port if that default one is
occupied. This is independent from the GUI configuration default address
defined in the protobuf description. More importantly, it ignores any
`STGUIADDRESS` override given via environment variable or command-line
option, thus probing for the default port instead of the one specified
via override.

The `ProbeFreePorts()` function now respects the override, by reading
the `GUIConfiguration.Address()` method instead of using hard-coded
defaults.

When not calling `ProbeFreePorts()`, the override should still be
persisted rather than the default address. This happens only when
generating a fresh default `config.xml`, never on an existing one.
2024-11-19 11:01:43 +00:00
Jakob Borg
e82ed6e3d3 style: gofumpt all the things (#9829)
Literally `gofumpt -w .` from the top level dir. Guaranteed to be minor
style changes only and nothing else.

@imsodin per request?
2024-11-19 11:32:56 +01:00
Syncthing Release Automation
4b815fc086 chore(gui, man, authors): update docs, translations, and contributors 2024-11-18 03:49:35 +00:00
Jakob Borg
7eaf843de2 chore(api): add block and goroutine profiles to support bundle (#9824) 2024-11-16 09:43:17 +01:00
Jakob Borg
110e1ae6f9 fix(model): don't panic in index consistency print (fixes #9821) (#9823)
We try to compare to the last fileinfo, but apparently we can end up
here with an empty file list and crash on out of index.
2024-11-14 19:59:34 +00:00
Jakob Borg
896f9725ec chore: update policy to allow approvals by contributors (#9818)
This adds `allow_contributor: true` which allows approvals by
contributors to the PR (but still not the author themself, which is a
different thing). This allows things like pushing minor fixups while
also approving.

The `ignore_update_merges: true` option makes it so that someone is not
considered a "contributor" just because they push the merge button to
update the branch. In principle this is not needed given the above, but
I like it for clarity.
2024-11-12 10:50:19 +01:00
Tobias Frölich
1a529e9d5d fix(gui): expand tildes for subdir check (fixes #9400) (#9788)
### Purpose

This closes #9400 by always expanding tildes when parent/subdir checks
are done.

### Testing

I tested this by creating folders with paths to parent or subdirectories
of the default folder that include a tilde in their path as shown in the
attached screenshots.
With this change, overlap will be detected regardless of wether or not
tildes are used in other folder paths.

### Screenshots

Default Folder:

![2024-10-26-At-08h40m33s](https://github.com/user-attachments/assets/07df090c-4481-41ec-b741-d2785fc848d5)
Newly created folder (parent directory in this case)

![2024-10-26-At-08h40m13s](https://github.com/user-attachments/assets/636fa1fd-41dc-44d9-ac90-0a4937c9921c)

---------

Signed-off-by: tobifroe <froeltob@pm.me>
2024-11-12 09:24:00 +01:00
Hireworks
36ef17df8f fix(model): check if remote folder state before pulling files (fixes #9686) (#9732)
### Purpose

As discussed in #9686 
Syncthing currently does not check folderstate on remote device before
pulling. If no devices have a valid folderstate (i.e all devices have
the folder paused) it will still attempt to pull. On large folders this
will cause a hanging "Syncing" status.

This checks whether at least one connected device has the file available
and has a valid folderstate.

### Testing
Tested locally on multiple devices.
We're new to Go (all our stuff is Python) so please bear with!
Interested if there may be a better place to slot this in.

Thanks,
Jon

---------

Co-authored-by: Simon Frei <freisim93@gmail.com>
2024-11-12 08:51:52 +01:00
Syncthing Release Automation
955ac7775e chore(gui, man, authors): update docs, translations, and contributors 2024-11-11 03:46:06 +00:00
tomasz1986
8f69e874c4 chore(gui): group logout/restart/shutdown buttons together in Actions menu (#9801)
Currently, the "Restart" and "Shutdown" buttons are displayed in the
middle of the Actions menu. On the other hand, the "Log Out" button is
displayed at the very bottom. However, in other cases, e.g. the menus in
operating systems like Windows or macOS, these kind of buttons are
usually grouped together.

Therefore, move the "Restart" and "Shutdown" buttons down, so that they
are listed together with the "Log Out" button. Also, change the order,
so that it goes from the least impactful ("Log Out") to the most
impactful ("Shutdown").

Signed-off-by: Tomasz Wilczyński <twilczynski@naver.com>

### Screenshots

#### Before


![image](https://github.com/user-attachments/assets/a51438ef-bb6f-4535-a972-8c1bc1dffa02)

#### After


![image](https://github.com/user-attachments/assets/535762d6-6f26-44ab-a402-db87bdcbfb36)

Signed-off-by: Tomasz Wilczyński <twilczynski@naver.com>
2024-11-07 16:47:00 +01:00
Syncthing Release Automation
ac06fd97e9 chore(gui, man, authors): update docs, translations, and contributors 2024-11-04 03:47:49 +00:00
Syncthing Release Automation
3726b7d112 chore(gui, man, authors): update docs, translations, and contributors 2024-10-28 03:48:15 +00:00
Ross Smith II
377200591e fix(fs): fix directory junction handling (fixes #9775) (#9786)
### Purpose

This fixes #9775. I also improved the comments as they were lacking.

My apologies for introducing this bug. In summary, the bug was
```
mode = mode ^ (ModeSymlink | ModeIrregular)
```
didn't correctly reset those bits. This correctly resets them:
```
mode = mode &^ ModeSymlink &^ ModeIrregular
```
Tested and working in Windows 11 version 10.0.22631.4317. I didn't test
in other versions, but I'm sure this is the only issue.
2024-10-27 16:08:38 +01:00
Kapil Sareen
4afc898c2f fix(model): don't sync symbolic links on Android (fixes #9725) (#9782) 2024-10-26 09:29:38 +00:00
Simon Frei
ff7e4fef55 chore(nat, upnp): Make failure logging less reptitive (ref #9324) (#9785)
Currently we log on every single one of 10 retries deep in the upnp
stack. However we also return the failure as an error, which is bubbled
up a while until it's logged at debug level. Switch that around, such
that the repeat logging happens at debug level but the top-level happens
at info. There's some chance that this will newly log errors from
nat-pmp that were previously hidden in debug level - I hope those are
useful and not too numerous.

Also potentially this can even close #9324, my (very limited)
understanding of the reports/discussion there is that there's likely no
problem with syncthing beyond the excessive logging, it's some weird
router behaviour.
2024-10-25 21:04:22 +00:00
Simon Frei
9ffddb1923 fix(gui): apply small screen CSS changes earlier (fixes #9590) (#9756)
These CSS overrides address issues that are already present on wider
screens, so apply it there. Some experiments show we might even want to
up the limit more, but I am chicken and lazy, so I propose to use the
existing 470px media block.

Supersedes another PR after not getting any reaction to feedback there:
https://github.com/syncthing/syncthing/pull/9591#issuecomment-2212586134

Co-authored-by: Jakob Borg <jakob@kastelo.net>
2024-10-25 22:49:22 +02:00
André Colomb
896b857fc4 fix(gui): hide lists with [object Object] in advanced settings (#9743)
As discussed in
https://github.com/syncthing/syncthing/pull/9175#discussion_r1730431703,
entries in advanced settings are unusable if they are comprised of a
list of objects. It just displays `[object Object], [object Object],
[object Object]`, e.g. for the devices a folder is shared with.

Filter out these config elements by detecting an array whose members are
not all strings or numbers, and setting them to `skip` type.

Fix some unnecessary repetition in calling `inputTypeFor()`, since it is
already cached in the `ng-init` directive.
2024-10-25 22:22:12 +02:00
Terrance
acc5d2675b fix(gui): add dark scheme styles for disabled checkboxes (fixes #9776) (#9777)
### Purpose

Fixes #9776 by tweaking the text/background colours of disabled checkbox
panels when dark mode is enabled.

It was [noted on that
issue](https://github.com/syncthing/syncthing/issues/9776#issuecomment-2424828520)
that there's a bigger issue around the correctness of using the
`disabled` attribute on a `<div>` in the first place, but this PR does
not attempt to change that.

### Testing

I've hooked up the GUI files against a release build as suggested below.

### Screenshots

Using the dark theme, or the default theme with a system dark scheme:


![image](https://github.com/user-attachments/assets/3c6bfa77-cc7a-4f3e-a5c2-83daf54dcc34)

Using the black theme:


![image](https://github.com/user-attachments/assets/768db657-aa52-4db0-8455-5194a00fc143)

These borrow the colours from dark theme text inputs and black theme
tabs for a consistent look (initially I tried the text colour of
disabled text inputs, but that produced some poor contrast).
2024-10-22 14:03:32 +02:00
Syncthing Release Automation
6ece4c1fd2 chore(gui, man, authors): update docs, translations, and contributors 2024-10-21 03:47:52 +00:00
Jakob Borg
cc09f0170d build(deps): update dependencies (#9773) 2024-10-17 13:05:53 +00:00
Syncthing Release Automation
bb234d6c0e chore(gui, man, authors): update docs, translations, and contributors 2024-10-14 03:47:49 +00:00
Syncthing Release Automation
e6acc64758 chore(gui, man, authors): update docs, translations, and contributors 2024-10-07 03:47:13 +00:00
André Colomb
f18cf545b9 fix(gui): improve device ID readability in black and dark themes (fixes #9757) (#9758) 2024-10-06 00:48:19 +02:00
320 changed files with 8676 additions and 29559 deletions

View File

@@ -3,11 +3,11 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
interval: monthly
open-pull-requests-limit: 10
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: weekly
interval: monthly
open-pull-requests-limit: 10

View File

@@ -12,12 +12,16 @@ env:
BUILD_USER: docker
BUILD_HOST: github.syncthing.net
permissions:
contents: read
packages: write
jobs:
docker-syncthing:
name: Build and push Docker images
if: github.repository == 'syncthing/syncthing'
runs-on: ubuntu-latest
environment: docker
environment: release
strategy:
matrix:
pkg:
@@ -41,6 +45,13 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build binaries
run: |
for arch in arm64 amd64; do
@@ -53,13 +64,13 @@ jobs:
- name: Set Docker tags (all branches)
run: |
tags=syncthing/${{ matrix.pkg }}:${{ github.sha }}
tags=docker.io/syncthing/${{ matrix.pkg }}:${{ github.sha }},ghcr.io/syncthing/infra/${{ matrix.pkg }}:${{ github.sha }}
echo "TAGS=$tags" >> $GITHUB_ENV
- name: Set Docker tags (latest)
if: github.ref == 'refs/heads/infrastructure'
run: |
tags=syncthing/${{ matrix.pkg }}:latest,${{ env.TAGS }}
tags=docker.io/syncthing/${{ matrix.pkg }}:latest,ghcr.io/syncthing/infra/${{ matrix.pkg }}:latest,${{ env.TAGS }}
echo "TAGS=$tags" >> $GITHUB_ENV
- name: Build and push

View File

@@ -83,8 +83,8 @@ jobs:
go run build.go test | go-test-json-to-loki
env:
GOFLAGS: "-json"
LOKI_URL: ${{ vars.LOKI_URL }}
LOKI_USER: ${{ vars.LOKI_USER }}
LOKI_URL: ${{ secrets.LOKI_URL }}
LOKI_USER: ${{ secrets.LOKI_USER }}
LOKI_PASSWORD: ${{ secrets.LOKI_PASSWORD }}
LOKI_LABELS: "go=${{ matrix.go }},runner=${{ matrix.runner }},repo=${{ github.repository }},ref=${{ github.ref }}"
@@ -137,8 +137,8 @@ jobs:
package-windows:
name: Package for Windows
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-'))
environment: signing
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v'))
environment: release
runs-on: windows-latest
steps:
- name: Set git to use LF
@@ -153,6 +153,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5
with:
@@ -178,10 +179,13 @@ jobs:
- name: Create packages
run: |
go run build.go -goarch amd64 zip
go run build.go -goarch arm zip
go run build.go -goarch arm64 zip
go run build.go -goarch 386 zip
$targets = 'syncthing', 'stdiscosrv', 'strelaysrv'
$archs = 'amd64', 'arm', 'arm64', '386'
foreach ($arch in $archs) {
foreach ($tgt in $targets) {
go run build.go -goarch $arch zip $tgt
}
}
env:
CGO_ENABLED: "0"
CODESIGN_SIGNTOOL: ${{ secrets.CODESIGN_SIGNTOOL }}
@@ -193,7 +197,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: packages-windows
path: syncthing-windows-*.zip
path: "*.zip"
#
# Linux
@@ -206,6 +210,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5
with:
@@ -229,7 +234,9 @@ jobs:
run: |
archs=$(go tool dist list | grep linux | sed 's#linux/##')
for goarch in $archs ; do
go run build.go -goarch "$goarch" tar
for tgt in syncthing stdiscosrv strelaysrv ; do
go run build.go -goarch "$goarch" tar "$tgt"
done
done
env:
CGO_ENABLED: "0"
@@ -239,7 +246,7 @@ jobs:
with:
name: packages-linux
path: |
syncthing-linux-*.tar.gz
*.tar.gz
compat.json
#
@@ -248,13 +255,14 @@ jobs:
package-macos:
name: Package for macOS
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-'))
environment: signing
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v'))
environment: release
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5
with:
@@ -301,7 +309,9 @@ jobs:
- name: Create package (amd64)
run: |
go run build.go -goarch amd64 zip
for tgt in syncthing stdiscosrv strelaysrv ; do
go run build.go -goarch amd64 zip "$tgt"
done
env:
CGO_ENABLED: "1"
@@ -315,7 +325,9 @@ jobs:
go "\$@"
EOT
chmod 755 xgo.sh
go run build.go -gocmd ./xgo.sh -goarch arm64 zip
for tgt in syncthing stdiscosrv strelaysrv ; do
go run build.go -gocmd ./xgo.sh -goarch arm64 zip "$tgt"
done
env:
CGO_ENABLED: "1"
@@ -339,15 +351,14 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: packages-macos
path: syncthing-*.zip
path: "*.zip"
notarize-macos:
name: Notarize for macOS
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-'))
environment: signing
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v'))
environment: release
needs:
- package-macos
- basics
runs-on: macos-latest
steps:
- name: Download artifacts
@@ -359,7 +370,7 @@ jobs:
run: |
APPSTORECONNECT_API_KEY_PATH="$RUNNER_TEMP/apikey.p8"
echo "$APPSTORECONNECT_API_KEY" | base64 -d -o "$APPSTORECONNECT_API_KEY_PATH"
for file in syncthing-macos-*.zip ; do
for file in *-macos-*.zip ; do
xcrun notarytool submit \
-k "$APPSTORECONNECT_API_KEY_PATH" \
-d "$APPSTORECONNECT_API_KEY_ID" \
@@ -382,6 +393,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5
with:
@@ -424,9 +436,11 @@ jobs:
goos="${plat%/*}"
goarch="${plat#*/}"
echo "::group ::$plat"
if ! go run build.go -goos "$goos" -goarch "$goarch" tar 2>/dev/null; then
echo "::warning ::Failed to build for $plat"
fi
for tgt in syncthing stdiscosrv strelaysrv ; do
if ! go run build.go -goos "$goos" -goarch "$goarch" tar "$tgt" 2>/dev/null; then
echo "::warning ::Failed to build $tgt for $plat"
fi
done
echo "::endgroup::"
done
env:
@@ -436,7 +450,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: packages-other
path: syncthing-*.tar.gz
path: "*.tar.gz"
#
# Source
@@ -449,6 +463,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5
with:
@@ -484,10 +499,9 @@ jobs:
sign-for-upgrade:
name: Sign for upgrade
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-'))
environment: signing
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v'))
environment: release
needs:
- basics
- package-windows
- package-linux
- package-macos
@@ -498,6 +512,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/checkout@v4
with:
@@ -531,30 +546,44 @@ jobs:
env:
STSIGTOOL_PRIVATE_KEY: ${{ secrets.STSIGTOOL_PRIVATE_KEY }}
- name: Create and sign .asc files
- name: Create shasum files
run: |
sudo apt update
sudo apt -y install gnupg
export SIGNING_KEY="$RUNNER_TEMP/gpg-secret.asc"
echo "$GNUPG_SIGNING_KEY_BASE64" | base64 -d > "$SIGNING_KEY"
gpg --import < "$SIGNING_KEY"
pushd packages
files=(*.tar.gz *.zip)
sha1sum "${files[@]}" | gpg --clearsign > sha1sum.txt.asc
sha256sum "${files[@]}" | gpg --clearsign > sha256sum.txt.asc
gpg --sign --armour --detach syncthing-source-*.tar.gz
sha1sum "${files[@]}" > sha1sum.txt
sha256sum "${files[@]}" > sha256sum.txt
popd
rm -f "$SIGNING_KEY" .gnupg
version=$(go run build.go version)
echo "VERSION=$version" >> $GITHUB_ENV
- name: Sign shasum files
uses: docker://ghcr.io/kastelo/ezapt:latest
with:
args:
sign
packages/sha1sum.txt packages/sha256sum.txt
env:
GNUPG_SIGNING_KEY_BASE64: ${{ secrets.GNUPG_SIGNING_KEY_BASE64 }}
EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
- name: Sign source
uses: docker://ghcr.io/kastelo/ezapt:latest
with:
args:
sign --detach --ascii
packages/syncthing-source-${{ env.VERSION }}.tar.gz
env:
EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
- name: Archive artifacts
uses: actions/upload-artifact@v4
with:
name: packages-signed
path: packages/*
path: |
packages/*.tar.gz
packages/*.zip
packages/*.asc
packages/*.json
#
# Debian
@@ -567,6 +596,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5
with:
@@ -597,7 +627,9 @@ jobs:
- name: Package for Debian
run: |
for arch in amd64 i386 armhf armel arm64 ; do
go run build.go -no-upgrade -installsuffix=no-upgrade -goarch "$arch" deb
for tgt in syncthing stdiscosrv strelaysrv ; do
go run build.go -no-upgrade -installsuffix=no-upgrade -goarch "$arch" deb "$tgt"
done
done
env:
BUILD_USER: debian
@@ -615,10 +647,9 @@ jobs:
publish-nightly:
name: Publish nightly build
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && startsWith(github.ref, 'refs/heads/release-nightly')
environment: signing
environment: release
needs:
- sign-for-upgrade
- notarize-macos
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -665,8 +696,8 @@ jobs:
publish-release-files:
name: Publish release files
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/release'
environment: signing
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/tags/v'))
environment: release
needs:
- sign-for-upgrade
- package-debian
@@ -675,6 +706,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- name: Download signed packages
uses: actions/download-artifact@v4
@@ -725,6 +757,84 @@ jobs:
with:
args: sync objstore:${{ secrets.S3_BUCKET }}/release/${{ env.VERSION }} objstore:${{ secrets.S3_BUCKET }}/release/latest
#
# Push Debian/APT archive
#
publish-apt:
name: Publish APT
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v'))
environment: release
needs:
- package-debian
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- name: Download packages
uses: actions/download-artifact@v4
with:
name: debian-packages
path: packages
- name: Set version
run: |
version=$(go run build.go version)
echo "Version: $version"
echo "VERSION=$version" >> $GITHUB_ENV
# Decide whether packages should go to stable, candidate or nightly
- name: Prepare packages
run: |
kind=stable
if [[ $VERSION == *-rc.[0-9] ]] ; then
kind=candidate
elif [[ $VERSION == *-* ]] ; then
kind=nightly
fi
echo "Kind: $kind"
mkdir -p packages/syncthing/$kind
mv packages/*.deb packages/syncthing/$kind
- name: Pull archive
uses: docker://docker.io/rclone/rclone:latest
env:
RCLONE_CONFIG_OBJSTORE_TYPE: s3
RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
RCLONE_CONFIG_OBJSTORE_ACL: public-read
with:
args: sync objstore:syncthing-apt/dists dists
- name: Update archive
uses: docker://ghcr.io/kastelo/ezapt:latest
with:
args:
publish
--add packages
--dists dists
env:
EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
- name: Push archive
uses: docker://docker.io/rclone/rclone:latest
env:
RCLONE_CONFIG_OBJSTORE_TYPE: s3
RCLONE_CONFIG_OBJSTORE_PROVIDER: ${{ secrets.S3_PROVIDER }}
RCLONE_CONFIG_OBJSTORE_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
RCLONE_CONFIG_OBJSTORE_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
RCLONE_CONFIG_OBJSTORE_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
RCLONE_CONFIG_OBJSTORE_ACL: public-read
with:
args: sync dists -v objstore:syncthing-apt/dists
#
# Build and push to Docker Hub
#
@@ -732,8 +842,11 @@ jobs:
docker-syncthing:
name: Build and push Docker images
runs-on: ubuntu-latest
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/infrastructure' || startsWith(github.ref, 'refs/heads/release-'))
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release' || github.ref == 'refs/heads/infrastructure' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v'))
environment: docker
permissions:
contents: read
packages: write
strategy:
matrix:
pkg:
@@ -754,6 +867,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5
with:
@@ -793,9 +907,18 @@ jobs:
uses: docker/login-action@v3
if: env.DOCKER_PUSH == 'true'
with:
registry: docker.io
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR
uses: docker/login-action@v3
if: env.DOCKER_PUSH == 'true'
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -807,13 +930,13 @@ jobs:
echo Release version, pushing to :latest and version tags
major=${version%.*.*}
minor=${version%.*}
tags=${{ matrix.image }}:$version,${{ matrix.image }}:$major,${{ matrix.image }}:$minor,${{ matrix.image }}:latest
tags=docker.io/${{ matrix.image }}:$version,ghcr.io/${{ matrix.image }}:$version,docker.io/${{ matrix.image }}:$major,ghcr.io/${{ matrix.image }}:$major,docker.io/${{ matrix.image }}:$minor,ghcr.io/${{ matrix.image }}:$minor,docker.io/${{ matrix.image }}:latest,ghcr.io/${{ matrix.image }}:latest
elif [[ $version == *-rc.@([0-9]|[0-9][0-9]) ]] ; then
echo Release candidate, pushing to :rc
tags=${{ matrix.image }}:rc
echo Release candidate, pushing to :rc and version tags
tags=docker.io/${{ matrix.image }}:$version,ghcr.io/${{ matrix.image }}:$version,docker.io/${{ matrix.image }}:rc,ghcr.io/${{ matrix.image }}:rc
else
echo Development version, pushing to :edge
tags=${{ matrix.image }}:edge
tags=docker.io/${{ matrix.image }}:edge,ghcr.io/${{ matrix.image }}:edge
fi
echo "DOCKER_TAGS=$tags" >> $GITHUB_ENV
echo "VERSION=$version" >> $GITHUB_ENV

View File

@@ -1,26 +1,39 @@
linters-settings:
maligned:
suggest-new: true
linters:
enable-all: true
disable:
- goimports
- cyclop
- depguard
- lll
- gochecknoinits
- gochecknoglobals
- gofmt
- scopelint
- gocyclo
- exhaustive
- exhaustruct
- funlen
- wsl
- gci
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
- gocyclo
- godox
- gofmt
- goimports
- gomoddirectives
- inamedparam
- interfacebloat
- ireturn
- lll
- maintidx
- nestif
- nonamedreturns
- paralleltest
- protogetter
- scopelint
- tagalign
- tagliatelle
- testpackage
- varnamelen
- wsl
service:
golangci-lint-version: 1.21.x
prepare:
- rm -f go.sum # 1.12 -> 1.13 issues with QUIC-go
- GO111MODULE=on go mod vendor
- go run build.go assets
issues:
exclude-dirs:
- internal/gen
- cmd/dev
- repos

View File

@@ -48,6 +48,9 @@ approval_rules:
count: 1
teams:
- syncthing/maintainers
options:
ignore_update_merges: true
allow_contributor: true
# Regular pull requests require approval by an active contributor
- name: is approved by a syncthing contributor
@@ -55,6 +58,9 @@ approval_rules:
count: 1
teams:
- syncthing/contributors
options:
ignore_update_merges: true
allow_contributor: true
# Changes to some files (translations, dependencies, compatibility) do not
# require approval if they were proposed by a contributor and have a

View File

@@ -20,6 +20,7 @@ Alan Pope <alan@popey.com>
Alberto Donato <albertodonato@users.noreply.github.com>
Aleksey Vasenev <margtu-fivt@ya.ru>
Alessandro G. (alessandro.g89) <alessandro.g89@gmail.com>
Alex Ionescu <github@ionescu.sh>
Alex Lindeman <139387+aelindeman@users.noreply.github.com>
Alex Xu <alex.hello71@gmail.com>
Alexander Graf (alex2108) <register-github@alex-graf.de>
@@ -146,6 +147,7 @@ Han Boetes <han@boetes.org>
HansK-p <42314815+HansK-p@users.noreply.github.com>
Harrison Jones (harrisonhjones) <harrisonhjones@users.noreply.github.com>
Heiko Zuerker (Smiley73) <heiko@zuerker.org>
Hireworks <129852174+hireworksltd@users.noreply.github.com>
Hugo Locurcio <hugo.locurcio@hugo.pro>
Iain Barnett <iainspeed@gmail.com>
Ian Johnson (anonymouse64) <ian.johnson@canonical.com> <person.uwsome@gmail.com>
@@ -189,6 +191,7 @@ Jörg Thalheim <Mic92@users.noreply.github.com>
Jędrzej Kula <kula.jedrek@gmail.com>
K.B.Dharun Krishna <kbdharunkrishna@gmail.com>
Kalle Laine <pahakalle@protonmail.com>
Kapil Sareen <kapilsareen584@gmail.com>
Karol Różycki (krozycki) <rozycki.karol@gmail.com>
Kebin Liu <lkebin@gmail.com>
Keith Harrison <keithh@protonmail.com>
@@ -318,11 +321,13 @@ Sven Bachmann <dev@mcbachmann.de>
Syncthing Automation <automation@syncthing.net>
Syncthing Release Automation <release@syncthing.net>
Taylor Khan (nelsonkhan) <nelsonkhan@gmail.com>
Terrance <git@terrance.allofti.me>
Thomas <9749173+uhthomas@users.noreply.github.com>
Thomas Hipp <thomashipp@gmail.com>
Tim Abell (timabell) <tim@timwise.co.uk>
Tim Howes (timhowes) <timhowes@berkeley.edu>
Tim Nordenfur <tim@gurka.se>
Tobias Frölich <40638719+tobifroe@users.noreply.github.com>
Tobias Klauser <tobias.klauser@gmail.com>
Tobias Nygren (tnn2) <tnn@nygren.pp.se>
Tobias Tom (tobiastom) <t.tom@succont.de>

View File

@@ -82,13 +82,11 @@ build process.
## Signed Releases
As of v0.10.15 and onwards, release binaries are GPG signed with the key
D26E6ED000654A3E, available from https://syncthing.net/security/ and
most key servers.
There is also a built-in automatic upgrade mechanism (disabled in some
distribution channels) which uses a compiled in ECDSA signature. macOS
binaries are also properly code signed.
Release binaries are GPG signed with the key available from
https://syncthing.net/security/. There is also a built-in automatic
upgrade mechanism (disabled in some distribution channels) which uses a
compiled in ECDSA signature. macOS and Windows binaries are also
code-signed.
## Documentation

12
buf.gen.yaml Normal file
View File

@@ -0,0 +1,12 @@
version: v2
managed:
enabled: true
override:
- file_option: go_package_prefix
value: github.com/syncthing/syncthing/internal/gen
plugins:
- remote: buf.build/protocolbuffers/go:v1.35.1
out: .
opt: module=github.com/syncthing/syncthing
inputs:
- directory: proto

10
buf.yaml Normal file
View File

@@ -0,0 +1,10 @@
version: v2
modules:
- path: proto
name: github.com/syncthing/syncthing
lint:
use:
- STANDARD
breaking:
use:
- WIRE_JSON

174
build.go
View File

@@ -86,7 +86,6 @@ var targets = map[string]target{
"all": {
// Only valid for the "build" and "install" commands as it lacks all
// the archive creation stuff. buildPkgs gets filled out in init()
tags: []string{"purego"},
},
"syncthing": {
// The default target for "build", "install", "tar", "zip", "deb", etc.
@@ -97,40 +96,40 @@ var targets = map[string]target{
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/syncthing"},
binaryName: "syncthing", // .exe will be added automatically for Windows builds
archiveFiles: []archiveFile{
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
{src: "README.md", dst: "README.txt", perm: 0644},
{src: "LICENSE", dst: "LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0644},
{src: "{{binary}}", dst: "{{binary}}", perm: 0o755},
{src: "README.md", dst: "README.txt", perm: 0o644},
{src: "LICENSE", dst: "LICENSE.txt", perm: 0o644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0o644},
// All files from etc/ and extra/ added automatically in init().
},
systemdService: "syncthing@*.service",
installationFiles: []archiveFile{
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0755},
{src: "README.md", dst: "deb/usr/share/doc/syncthing/README.txt", perm: 0644},
{src: "LICENSE", dst: "deb/usr/share/doc/syncthing/LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing/AUTHORS.txt", perm: 0644},
{src: "man/syncthing.1", dst: "deb/usr/share/man/man1/syncthing.1", perm: 0644},
{src: "man/syncthing-config.5", dst: "deb/usr/share/man/man5/syncthing-config.5", perm: 0644},
{src: "man/syncthing-stignore.5", dst: "deb/usr/share/man/man5/syncthing-stignore.5", perm: 0644},
{src: "man/syncthing-device-ids.7", dst: "deb/usr/share/man/man7/syncthing-device-ids.7", perm: 0644},
{src: "man/syncthing-event-api.7", dst: "deb/usr/share/man/man7/syncthing-event-api.7", perm: 0644},
{src: "man/syncthing-faq.7", dst: "deb/usr/share/man/man7/syncthing-faq.7", perm: 0644},
{src: "man/syncthing-networking.7", dst: "deb/usr/share/man/man7/syncthing-networking.7", perm: 0644},
{src: "man/syncthing-rest-api.7", dst: "deb/usr/share/man/man7/syncthing-rest-api.7", perm: 0644},
{src: "man/syncthing-security.7", dst: "deb/usr/share/man/man7/syncthing-security.7", perm: 0644},
{src: "man/syncthing-versioning.7", dst: "deb/usr/share/man/man7/syncthing-versioning.7", perm: 0644},
{src: "etc/linux-systemd/system/syncthing@.service", dst: "deb/lib/systemd/system/syncthing@.service", perm: 0644},
{src: "etc/linux-systemd/user/syncthing.service", dst: "deb/usr/lib/systemd/user/syncthing.service", perm: 0644},
{src: "etc/linux-sysctl/30-syncthing.conf", dst: "deb/usr/lib/sysctl.d/30-syncthing.conf", perm: 0644},
{src: "etc/firewall-ufw/syncthing", dst: "deb/etc/ufw/applications.d/syncthing", perm: 0644},
{src: "etc/linux-desktop/syncthing-start.desktop", dst: "deb/usr/share/applications/syncthing-start.desktop", perm: 0644},
{src: "etc/linux-desktop/syncthing-ui.desktop", dst: "deb/usr/share/applications/syncthing-ui.desktop", perm: 0644},
{src: "assets/logo-32.png", dst: "deb/usr/share/icons/hicolor/32x32/apps/syncthing.png", perm: 0644},
{src: "assets/logo-64.png", dst: "deb/usr/share/icons/hicolor/64x64/apps/syncthing.png", perm: 0644},
{src: "assets/logo-128.png", dst: "deb/usr/share/icons/hicolor/128x128/apps/syncthing.png", perm: 0644},
{src: "assets/logo-256.png", dst: "deb/usr/share/icons/hicolor/256x256/apps/syncthing.png", perm: 0644},
{src: "assets/logo-512.png", dst: "deb/usr/share/icons/hicolor/512x512/apps/syncthing.png", perm: 0644},
{src: "assets/logo-only.svg", dst: "deb/usr/share/icons/hicolor/scalable/apps/syncthing.svg", perm: 0644},
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0o755},
{src: "README.md", dst: "deb/usr/share/doc/syncthing/README.txt", perm: 0o644},
{src: "LICENSE", dst: "deb/usr/share/doc/syncthing/LICENSE.txt", perm: 0o644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing/AUTHORS.txt", perm: 0o644},
{src: "man/syncthing.1", dst: "deb/usr/share/man/man1/syncthing.1", perm: 0o644},
{src: "man/syncthing-config.5", dst: "deb/usr/share/man/man5/syncthing-config.5", perm: 0o644},
{src: "man/syncthing-stignore.5", dst: "deb/usr/share/man/man5/syncthing-stignore.5", perm: 0o644},
{src: "man/syncthing-device-ids.7", dst: "deb/usr/share/man/man7/syncthing-device-ids.7", perm: 0o644},
{src: "man/syncthing-event-api.7", dst: "deb/usr/share/man/man7/syncthing-event-api.7", perm: 0o644},
{src: "man/syncthing-faq.7", dst: "deb/usr/share/man/man7/syncthing-faq.7", perm: 0o644},
{src: "man/syncthing-networking.7", dst: "deb/usr/share/man/man7/syncthing-networking.7", perm: 0o644},
{src: "man/syncthing-rest-api.7", dst: "deb/usr/share/man/man7/syncthing-rest-api.7", perm: 0o644},
{src: "man/syncthing-security.7", dst: "deb/usr/share/man/man7/syncthing-security.7", perm: 0o644},
{src: "man/syncthing-versioning.7", dst: "deb/usr/share/man/man7/syncthing-versioning.7", perm: 0o644},
{src: "etc/linux-systemd/system/syncthing@.service", dst: "deb/lib/systemd/system/syncthing@.service", perm: 0o644},
{src: "etc/linux-systemd/user/syncthing.service", dst: "deb/usr/lib/systemd/user/syncthing.service", perm: 0o644},
{src: "etc/linux-sysctl/30-syncthing.conf", dst: "deb/usr/lib/sysctl.d/30-syncthing.conf", perm: 0o644},
{src: "etc/firewall-ufw/syncthing", dst: "deb/etc/ufw/applications.d/syncthing", perm: 0o644},
{src: "etc/linux-desktop/syncthing-start.desktop", dst: "deb/usr/share/applications/syncthing-start.desktop", perm: 0o644},
{src: "etc/linux-desktop/syncthing-ui.desktop", dst: "deb/usr/share/applications/syncthing-ui.desktop", perm: 0o644},
{src: "assets/logo-32.png", dst: "deb/usr/share/icons/hicolor/32x32/apps/syncthing.png", perm: 0o644},
{src: "assets/logo-64.png", dst: "deb/usr/share/icons/hicolor/64x64/apps/syncthing.png", perm: 0o644},
{src: "assets/logo-128.png", dst: "deb/usr/share/icons/hicolor/128x128/apps/syncthing.png", perm: 0o644},
{src: "assets/logo-256.png", dst: "deb/usr/share/icons/hicolor/256x256/apps/syncthing.png", perm: 0o644},
{src: "assets/logo-512.png", dst: "deb/usr/share/icons/hicolor/512x512/apps/syncthing.png", perm: 0o644},
{src: "assets/logo-only.svg", dst: "deb/usr/share/icons/hicolor/scalable/apps/syncthing.svg", perm: 0o644},
},
},
"stdiscosrv": {
@@ -142,23 +141,22 @@ var targets = map[string]target{
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/stdiscosrv"},
binaryName: "stdiscosrv", // .exe will be added automatically for Windows builds
archiveFiles: []archiveFile{
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
{src: "cmd/stdiscosrv/README.md", dst: "README.txt", perm: 0644},
{src: "LICENSE", dst: "LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0644},
{src: "{{binary}}", dst: "{{binary}}", perm: 0o755},
{src: "cmd/stdiscosrv/README.md", dst: "README.txt", perm: 0o644},
{src: "LICENSE", dst: "LICENSE.txt", perm: 0o644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0o644},
},
systemdService: "stdiscosrv.service",
installationFiles: []archiveFile{
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0755},
{src: "cmd/stdiscosrv/README.md", dst: "deb/usr/share/doc/syncthing-discosrv/README.txt", perm: 0644},
{src: "LICENSE", dst: "deb/usr/share/doc/syncthing-discosrv/LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing-discosrv/AUTHORS.txt", perm: 0644},
{src: "man/stdiscosrv.1", dst: "deb/usr/share/man/man1/stdiscosrv.1", perm: 0644},
{src: "cmd/stdiscosrv/etc/linux-systemd/stdiscosrv.service", dst: "deb/lib/systemd/system/stdiscosrv.service", perm: 0644},
{src: "cmd/stdiscosrv/etc/linux-systemd/default", dst: "deb/etc/default/syncthing-discosrv", perm: 0644},
{src: "cmd/stdiscosrv/etc/firewall-ufw/stdiscosrv", dst: "deb/etc/ufw/applications.d/stdiscosrv", perm: 0644},
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0o755},
{src: "cmd/stdiscosrv/README.md", dst: "deb/usr/share/doc/syncthing-discosrv/README.txt", perm: 0o644},
{src: "LICENSE", dst: "deb/usr/share/doc/syncthing-discosrv/LICENSE.txt", perm: 0o644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing-discosrv/AUTHORS.txt", perm: 0o644},
{src: "man/stdiscosrv.1", dst: "deb/usr/share/man/man1/stdiscosrv.1", perm: 0o644},
{src: "cmd/stdiscosrv/etc/linux-systemd/stdiscosrv.service", dst: "deb/lib/systemd/system/stdiscosrv.service", perm: 0o644},
{src: "cmd/stdiscosrv/etc/linux-systemd/default", dst: "deb/etc/default/syncthing-discosrv", perm: 0o644},
{src: "cmd/stdiscosrv/etc/firewall-ufw/stdiscosrv", dst: "deb/etc/ufw/applications.d/stdiscosrv", perm: 0o644},
},
tags: []string{"purego"},
},
"strelaysrv": {
name: "strelaysrv",
@@ -169,44 +167,30 @@ var targets = map[string]target{
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/strelaysrv"},
binaryName: "strelaysrv", // .exe will be added automatically for Windows builds
archiveFiles: []archiveFile{
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
{src: "cmd/strelaysrv/README.md", dst: "README.txt", perm: 0644},
{src: "cmd/strelaysrv/LICENSE", dst: "LICENSE.txt", perm: 0644},
{src: "LICENSE", dst: "LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0644},
{src: "{{binary}}", dst: "{{binary}}", perm: 0o755},
{src: "cmd/strelaysrv/README.md", dst: "README.txt", perm: 0o644},
{src: "cmd/strelaysrv/LICENSE", dst: "LICENSE.txt", perm: 0o644},
{src: "LICENSE", dst: "LICENSE.txt", perm: 0o644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0o644},
},
systemdService: "strelaysrv.service",
installationFiles: []archiveFile{
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0755},
{src: "cmd/strelaysrv/README.md", dst: "deb/usr/share/doc/syncthing-relaysrv/README.txt", perm: 0644},
{src: "cmd/strelaysrv/LICENSE", dst: "deb/usr/share/doc/syncthing-relaysrv/LICENSE.txt", perm: 0644},
{src: "LICENSE", dst: "deb/usr/share/doc/syncthing-relaysrv/LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing-relaysrv/AUTHORS.txt", perm: 0644},
{src: "man/strelaysrv.1", dst: "deb/usr/share/man/man1/strelaysrv.1", perm: 0644},
{src: "cmd/strelaysrv/etc/linux-systemd/strelaysrv.service", dst: "deb/lib/systemd/system/strelaysrv.service", perm: 0644},
{src: "cmd/strelaysrv/etc/linux-systemd/default", dst: "deb/etc/default/syncthing-relaysrv", perm: 0644},
{src: "cmd/strelaysrv/etc/firewall-ufw/strelaysrv", dst: "deb/etc/ufw/applications.d/strelaysrv", perm: 0644},
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0o755},
{src: "cmd/strelaysrv/README.md", dst: "deb/usr/share/doc/syncthing-relaysrv/README.txt", perm: 0o644},
{src: "cmd/strelaysrv/LICENSE", dst: "deb/usr/share/doc/syncthing-relaysrv/LICENSE.txt", perm: 0o644},
{src: "LICENSE", dst: "deb/usr/share/doc/syncthing-relaysrv/LICENSE.txt", perm: 0o644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing-relaysrv/AUTHORS.txt", perm: 0o644},
{src: "man/strelaysrv.1", dst: "deb/usr/share/man/man1/strelaysrv.1", perm: 0o644},
{src: "cmd/strelaysrv/etc/linux-systemd/strelaysrv.service", dst: "deb/lib/systemd/system/strelaysrv.service", perm: 0o644},
{src: "cmd/strelaysrv/etc/linux-systemd/default", dst: "deb/etc/default/syncthing-relaysrv", perm: 0o644},
{src: "cmd/strelaysrv/etc/firewall-ufw/strelaysrv", dst: "deb/etc/ufw/applications.d/strelaysrv", perm: 0o644},
},
},
"strelaypoolsrv": {
name: "strelaypoolsrv",
debname: "syncthing-relaypoolsrv",
debdeps: []string{"libc6"},
description: "Syncthing Relay Pool Server",
buildPkgs: []string{"github.com/syncthing/syncthing/cmd/infra/strelaypoolsrv"},
binaryName: "strelaypoolsrv", // .exe will be added automatically for Windows builds
archiveFiles: []archiveFile{
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
{src: "cmd/infra/strelaypoolsrv/README.md", dst: "README.txt", perm: 0644},
{src: "cmd/infra/strelaypoolsrv/LICENSE", dst: "LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0644},
},
installationFiles: []archiveFile{
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0755},
{src: "cmd/infra/strelaypoolsrv/README.md", dst: "deb/usr/share/doc/syncthing-relaypoolsrv/README.txt", perm: 0644},
{src: "cmd/infra/strelaypoolsrv/LICENSE", dst: "deb/usr/share/doc/syncthing-relaypoolsrv/LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing-relaypoolsrv/AUTHORS.txt", perm: 0644},
},
binaryName: "strelaypoolsrv",
},
"stupgrades": {
name: "stupgrades",
@@ -244,13 +228,13 @@ func initTargets() {
// and "extra" dirs.
syncthingPkg := targets["syncthing"]
for _, file := range listFiles("etc") {
syncthingPkg.archiveFiles = append(syncthingPkg.archiveFiles, archiveFile{src: file, dst: file, perm: 0644})
syncthingPkg.archiveFiles = append(syncthingPkg.archiveFiles, archiveFile{src: file, dst: file, perm: 0o644})
}
for _, file := range listFiles("extra") {
syncthingPkg.archiveFiles = append(syncthingPkg.archiveFiles, archiveFile{src: file, dst: file, perm: 0644})
syncthingPkg.archiveFiles = append(syncthingPkg.archiveFiles, archiveFile{src: file, dst: file, perm: 0o644})
}
for _, file := range listFiles("extra") {
syncthingPkg.installationFiles = append(syncthingPkg.installationFiles, archiveFile{src: file, dst: "deb/usr/share/doc/syncthing/" + filepath.Base(file), perm: 0644})
syncthingPkg.installationFiles = append(syncthingPkg.installationFiles, archiveFile{src: file, dst: "deb/usr/share/doc/syncthing/" + filepath.Base(file), perm: 0o644})
}
targets["syncthing"] = syncthingPkg
}
@@ -405,7 +389,6 @@ func parseFlags() {
func test(tags []string, pkgs ...string) {
lazyRebuildAssets()
tags = append(tags, "purego")
args := []string{"test", "-tags", strings.Join(tags, " ")}
if long {
timeout = longTimeout
@@ -439,7 +422,7 @@ func bench(tags []string, pkgs ...string) {
func integration(bench bool) {
lazyRebuildAssets()
args := []string{"test", "-v", "-timeout", "60m", "-tags"}
tags := "purego,integration"
tags := "integration"
if bench {
tags += ",benchmark"
}
@@ -750,7 +733,7 @@ func shouldBuildSyso(dir string) (string, error) {
}
jsonPath := filepath.Join(dir, "versioninfo.json")
err = os.WriteFile(jsonPath, bs, 0644)
err = os.WriteFile(jsonPath, bs, 0o644)
if err != nil {
return "", errors.New("failed to create " + jsonPath + ": " + err.Error())
}
@@ -809,7 +792,7 @@ func copyFile(src, dst string, perm os.FileMode) error {
}
copy:
os.MkdirAll(filepath.Dir(dst), 0777)
os.MkdirAll(filepath.Dir(dst), 0o777)
if err := os.WriteFile(dst, in, perm); err != nil {
return err
}
@@ -869,7 +852,7 @@ func buildNextGenGUI() bool {
for _, src := range listFiles("next-gen-gui/dist") {
rel, _ := filepath.Rel("next-gen-gui/dist", src)
dst := filepath.Join("gui", rel)
if err := copyFile(src, dst, 0644); err != nil {
if err := copyFile(src, dst, 0o644); err != nil {
fmt.Println("copy:", err)
os.Exit(1)
}
@@ -925,22 +908,9 @@ func updateDependencies() {
}
func proto() {
pv := protobufVersion()
repo := "https://github.com/gogo/protobuf.git"
path := filepath.Join("repos", "protobuf")
runPrint(goCmd, "install", fmt.Sprintf("github.com/gogo/protobuf/protoc-gen-gogofast@%v", pv))
os.MkdirAll("repos", 0755)
if _, err := os.Stat(path); err != nil {
runPrint("git", "clone", repo, path)
} else {
runPrintInDir(path, "git", "fetch")
}
runPrintInDir(path, "git", "checkout", pv)
runPrint(goCmd, "generate", "github.com/syncthing/syncthing/cmd/stdiscosrv")
runPrint(goCmd, "generate", "proto/generate.go")
// buf needs to be installed
// https://buf.build/docs/installation/
runPrint("buf", "generate")
}
func testmocks() {
@@ -1427,7 +1397,7 @@ func windowsCodesign(file string) {
log.Println("Codesign: signing failed: creating temp file:", err)
return
}
_ = f.Chmod(0600) // best effort remove other users' access
_ = f.Chmod(0o600) // best effort remove other users' access
defer os.Remove(f.Name())
if _, err := f.Write(bs); err != nil {
log.Println("Codesign: signing failed: writing temp file:", err)
@@ -1483,14 +1453,6 @@ func (t target) BinaryName() string {
return t.binaryName
}
func protobufVersion() string {
bs, err := runError(goCmd, "list", "-f", "{{.Version}}", "-m", "github.com/gogo/protobuf")
if err != nil {
log.Fatal("Getting protobuf version:", err)
}
return string(bs)
}
func currentAndLatestVersions(n int) ([]string, error) {
bs, err := runError("git", "tag", "--sort", "taggerdate")
if err != nil {

View File

@@ -15,6 +15,9 @@ import (
"strings"
"time"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/discoproto"
_ "github.com/syncthing/syncthing/lib/automaxprocs"
"github.com/syncthing/syncthing/lib/beacon"
"github.com/syncthing/syncthing/lib/discover"
@@ -75,20 +78,21 @@ func recv(bc beacon.Interface) {
continue
}
var ann discover.Announce
ann.Unmarshal(data[4:])
var ann discoproto.Announce
proto.Unmarshal(data[4:], &ann)
if ann.ID == myID {
id, _ := protocol.DeviceIDFromBytes(ann.Id)
if id == myID {
// This is one of our own fake packets, don't print it.
continue
}
// Print announcement details for the first packet from a given
// device ID and source address, or if -all was given.
key := ann.ID.String() + src.String()
key := id.String() + src.String()
if all || !seen[key] {
log.Printf("Announcement from %v\n", src)
log.Printf(" %v at %s\n", ann.ID, strings.Join(ann.Addresses, ", "))
log.Printf(" %v at %s\n", id, strings.Join(ann.Addresses, ", "))
seen[key] = true
}
}
@@ -96,11 +100,11 @@ func recv(bc beacon.Interface) {
// sends fake discovery announcements once every second
func send(bc beacon.Interface) {
ann := discover.Announce{
ID: myID,
ann := &discoproto.Announce{
Id: myID[:],
Addresses: []string{"tcp://fake.example.com:12345"},
}
bs, _ := ann.Marshal()
bs, _ := proto.Marshal(ann)
for {
bc.Send(bs)

View File

@@ -71,7 +71,6 @@ func (l *githubSourceCodeLoader) Load(filename string, line, context int) ([][]b
url := urlPrefix + l.version + filename[idx:]
resp, err := l.client.Get(url)
if err != nil {
fmt.Println("Loading source:", err)
return nil, 0

View File

@@ -52,5 +52,5 @@ func compressAndWrite(bs []byte, fullPath string) error {
gw.Close()
// Create an output file with the compressed report
return os.WriteFile(fullPath, buf.Bytes(), 0644)
return os.WriteFile(fullPath, buf.Bytes(), 0o644)
}

View File

@@ -23,6 +23,7 @@ import (
lru "github.com/hashicorp/golang-lru/v2"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/syncthing/syncthing/cmd/infra/strelaypoolsrv/auto"
"github.com/syncthing/syncthing/lib/assets"
_ "github.com/syncthing/syncthing/lib/automaxprocs"

View File

@@ -17,17 +17,15 @@ import (
"log/slog"
"net"
"net/http"
_ "net/http/pprof"
"os"
"regexp"
"strings"
"time"
_ "net/http/pprof"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/puzpuzpuz/xsync/v3"
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/geoip"
"github.com/syncthing/syncthing/lib/s3"

View File

@@ -13,8 +13,12 @@ import (
"log"
amqp "github.com/rabbitmq/amqp091-go"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/thejerf/suture/v4"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/discosrv"
"github.com/syncthing/syncthing/internal/protoutil"
"github.com/syncthing/syncthing/lib/protocol"
)
type amqpReplicator struct {
@@ -22,7 +26,7 @@ type amqpReplicator struct {
broker string
sender *amqpSender
receiver *amqpReceiver
outbox chan ReplicationRecord
outbox chan *discosrv.ReplicationRecord
}
func newAMQPReplicator(broker, clientID string, db database) *amqpReplicator {
@@ -31,7 +35,7 @@ func newAMQPReplicator(broker, clientID string, db database) *amqpReplicator {
sender := &amqpSender{
broker: broker,
clientID: clientID,
outbox: make(chan ReplicationRecord, replicationOutboxSize),
outbox: make(chan *discosrv.ReplicationRecord, replicationOutboxSize),
}
svc.Add(sender)
@@ -47,18 +51,18 @@ func newAMQPReplicator(broker, clientID string, db database) *amqpReplicator {
broker: broker,
sender: sender,
receiver: receiver,
outbox: make(chan ReplicationRecord, replicationOutboxSize),
outbox: make(chan *discosrv.ReplicationRecord, replicationOutboxSize),
}
}
func (s *amqpReplicator) send(key *protocol.DeviceID, ps []DatabaseAddress, seen int64) {
func (s *amqpReplicator) send(key *protocol.DeviceID, ps []*discosrv.DatabaseAddress, seen int64) {
s.sender.send(key, ps, seen)
}
type amqpSender struct {
broker string
clientID string
outbox chan ReplicationRecord
outbox chan *discosrv.ReplicationRecord
}
func (s *amqpSender) Serve(ctx context.Context) error {
@@ -73,12 +77,12 @@ func (s *amqpSender) Serve(ctx context.Context) error {
for {
select {
case rec := <-s.outbox:
size := rec.Size()
size := proto.Size(rec)
if len(buf) < size {
buf = make([]byte, size)
}
n, err := rec.MarshalTo(buf)
n, err := protoutil.MarshalTo(buf, rec)
if err != nil {
replicationSendsTotal.WithLabelValues("error").Inc()
return fmt.Errorf("replication marshal: %w", err)
@@ -111,8 +115,8 @@ func (s *amqpSender) String() string {
return fmt.Sprintf("amqpSender(%q)", s.broker)
}
func (s *amqpSender) send(key *protocol.DeviceID, ps []DatabaseAddress, seen int64) {
item := ReplicationRecord{
func (s *amqpSender) send(key *protocol.DeviceID, ps []*discosrv.DatabaseAddress, seen int64) {
item := &discosrv.ReplicationRecord{
Key: key[:],
Addresses: ps,
Seen: seen,
@@ -158,8 +162,8 @@ func (s *amqpReceiver) Serve(ctx context.Context) error {
continue
}
var rec ReplicationRecord
if err := rec.Unmarshal(msg.Body); err != nil {
var rec discosrv.ReplicationRecord
if err := proto.Unmarshal(msg.Body, &rec); err != nil {
replicationRecvsTotal.WithLabelValues("error").Inc()
return fmt.Errorf("replication unmarshal: %w", err)
}

View File

@@ -28,6 +28,7 @@ import (
"sync"
"time"
"github.com/syncthing/syncthing/internal/gen/discosrv"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/stringutil"
)
@@ -52,7 +53,7 @@ type apiSrv struct {
}
type replicator interface {
send(key *protocol.DeviceID, addrs []DatabaseAddress, seen int64)
send(key *protocol.DeviceID, addrs []*discosrv.DatabaseAddress, seen int64)
}
type requestID int64
@@ -119,7 +120,9 @@ func (s *apiSrv) Serve(ctx context.Context) error {
ReadTimeout: httpReadTimeout,
WriteTimeout: httpWriteTimeout,
MaxHeaderBytes: httpMaxHeaderBytes,
ErrorLog: log.New(io.Discard, "", 0),
}
if !debug {
srv.ErrorLog = log.New(io.Discard, "", 0)
}
go func() {
@@ -195,7 +198,7 @@ func (s *apiSrv) handleGET(w http.ResponseWriter, req *http.Request) {
deviceID, err := protocol.DeviceIDFromString(req.URL.Query().Get("device"))
if err != nil {
if debug {
log.Println(reqID, "bad device param")
log.Println(reqID, "bad device param:", err)
}
lookupRequestsTotal.WithLabelValues("bad_request").Inc()
w.Header().Set("Retry-After", errorRetryAfterString())
@@ -280,6 +283,9 @@ func (s *apiSrv) handlePOST(remoteAddr *net.TCPAddr, w http.ResponseWriter, req
addresses := fixupAddresses(remoteAddr, ann.Addresses)
if len(addresses) == 0 {
if debug {
log.Println(reqID, "no addresses")
}
announceRequestsTotal.WithLabelValues("bad_request").Inc()
w.Header().Set("Retry-After", errorRetryAfterString())
http.Error(w, "Bad Request", http.StatusBadRequest)
@@ -287,6 +293,9 @@ func (s *apiSrv) handlePOST(remoteAddr *net.TCPAddr, w http.ResponseWriter, req
}
if err := s.handleAnnounce(deviceID, addresses); err != nil {
if debug {
log.Println(reqID, "handle:", err)
}
announceRequestsTotal.WithLabelValues("internal_error").Inc()
w.Header().Set("Retry-After", errorRetryAfterString())
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
@@ -297,6 +306,9 @@ func (s *apiSrv) handlePOST(remoteAddr *net.TCPAddr, w http.ResponseWriter, req
w.Header().Set("Reannounce-After", reannounceAfterString())
w.WriteHeader(http.StatusNoContent)
if debug {
log.Println(reqID, "announced", deviceID, addresses)
}
}
func (s *apiSrv) Stop() {
@@ -312,10 +324,12 @@ func (s *apiSrv) handleAnnounce(deviceID protocol.DeviceID, addresses []string)
slices.Sort(addresses)
addresses = slices.Compact(addresses)
dbAddrs := make([]DatabaseAddress, len(addresses))
dbAddrs := make([]*discosrv.DatabaseAddress, len(addresses))
for i := range addresses {
dbAddrs[i].Address = addresses[i]
dbAddrs[i].Expires = expire
dbAddrs[i] = &discosrv.DatabaseAddress{
Address: addresses[i],
Expires: expire,
}
}
seen := now.UnixNano()
@@ -326,7 +340,7 @@ func (s *apiSrv) handleAnnounce(deviceID protocol.DeviceID, addresses []string)
}
func handlePing(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(204)
w.WriteHeader(http.StatusNoContent)
}
func certificateBytes(req *http.Request) ([]byte, error) {
@@ -511,7 +525,7 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) {
lrw.ResponseWriter.WriteHeader(code)
}
func addressStrs(dbAddrs []DatabaseAddress) []string {
func addressStrs(dbAddrs []*discosrv.DatabaseAddress) []string {
res := make([]string, len(dbAddrs))
for i, a := range dbAddrs {
res[i] = a.Address

View File

@@ -4,9 +4,6 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
//go:generate go run ../../proto/scripts/protofmt.go database.proto
//go:generate protoc -I ../../ -I . --gogofast_out=. database.proto
package main
import (
@@ -25,6 +22,10 @@ import (
"time"
"github.com/puzpuzpuz/xsync/v3"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/discosrv"
"github.com/syncthing/syncthing/internal/protoutil"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/s3"
@@ -41,13 +42,13 @@ func (defaultClock) Now() time.Time {
}
type database interface {
put(key *protocol.DeviceID, rec DatabaseRecord) error
merge(key *protocol.DeviceID, addrs []DatabaseAddress, seen int64) error
get(key *protocol.DeviceID) (DatabaseRecord, error)
put(key *protocol.DeviceID, rec *discosrv.DatabaseRecord) error
merge(key *protocol.DeviceID, addrs []*discosrv.DatabaseAddress, seen int64) error
get(key *protocol.DeviceID) (*discosrv.DatabaseRecord, error)
}
type inMemoryStore struct {
m *xsync.MapOf[protocol.DeviceID, DatabaseRecord]
m *xsync.MapOf[protocol.DeviceID, *discosrv.DatabaseRecord]
dir string
flushInterval time.Duration
s3 *s3.Session
@@ -61,7 +62,7 @@ func newInMemoryStore(dir string, flushInterval time.Duration, s3sess *s3.Sessio
hn = rand.String(8)
}
s := &inMemoryStore{
m: xsync.NewMapOf[protocol.DeviceID, DatabaseRecord](),
m: xsync.NewMapOf[protocol.DeviceID, *discosrv.DatabaseRecord](),
dir: dir,
flushInterval: flushInterval,
s3: s3sess,
@@ -95,7 +96,7 @@ func newInMemoryStore(dir string, flushInterval time.Duration, s3sess *s3.Sessio
return s
}
func (s *inMemoryStore) put(key *protocol.DeviceID, rec DatabaseRecord) error {
func (s *inMemoryStore) put(key *protocol.DeviceID, rec *discosrv.DatabaseRecord) error {
t0 := time.Now()
s.m.Store(*key, rec)
databaseOperations.WithLabelValues(dbOpPut, dbResSuccess).Inc()
@@ -103,16 +104,17 @@ func (s *inMemoryStore) put(key *protocol.DeviceID, rec DatabaseRecord) error {
return nil
}
func (s *inMemoryStore) merge(key *protocol.DeviceID, addrs []DatabaseAddress, seen int64) error {
func (s *inMemoryStore) merge(key *protocol.DeviceID, addrs []*discosrv.DatabaseAddress, seen int64) error {
t0 := time.Now()
newRec := DatabaseRecord{
newRec := &discosrv.DatabaseRecord{
Addresses: addrs,
Seen: seen,
}
oldRec, _ := s.m.Load(*key)
newRec = merge(oldRec, newRec)
if oldRec, ok := s.m.Load(*key); ok {
newRec = merge(oldRec, newRec)
}
s.m.Store(*key, newRec)
databaseOperations.WithLabelValues(dbOpMerge, dbResSuccess).Inc()
@@ -121,7 +123,7 @@ func (s *inMemoryStore) merge(key *protocol.DeviceID, addrs []DatabaseAddress, s
return nil
}
func (s *inMemoryStore) get(key *protocol.DeviceID) (DatabaseRecord, error) {
func (s *inMemoryStore) get(key *protocol.DeviceID) (*discosrv.DatabaseRecord, error) {
t0 := time.Now()
defer func() {
databaseOperationSeconds.WithLabelValues(dbOpGet).Observe(time.Since(t0).Seconds())
@@ -130,7 +132,7 @@ func (s *inMemoryStore) get(key *protocol.DeviceID) (DatabaseRecord, error) {
rec, ok := s.m.Load(*key)
if !ok {
databaseOperations.WithLabelValues(dbOpGet, dbResNotFound).Inc()
return DatabaseRecord{}, nil
return &discosrv.DatabaseRecord{}, nil
}
rec.Addresses = expire(rec.Addresses, s.clock.Now())
@@ -176,7 +178,7 @@ func (s *inMemoryStore) expireAndCalculateStatistics() {
current, currentIPv4, currentIPv6, currentIPv6GUA, last24h, last1w := 0, 0, 0, 0, 0, 0
n := 0
s.m.Range(func(key protocol.DeviceID, rec DatabaseRecord) bool {
s.m.Range(func(key protocol.DeviceID, rec *discosrv.DatabaseRecord) bool {
if n%1000 == 0 {
runtime.Gosched()
}
@@ -261,7 +263,7 @@ func (s *inMemoryStore) write() (err error) {
now := s.clock.Now()
cutoff1w := now.Add(-7 * 24 * time.Hour).UnixNano()
n := 0
s.m.Range(func(key protocol.DeviceID, value DatabaseRecord) bool {
s.m.Range(func(key protocol.DeviceID, value *discosrv.DatabaseRecord) bool {
if n%1000 == 0 {
runtime.Gosched()
}
@@ -271,16 +273,16 @@ func (s *inMemoryStore) write() (err error) {
// drop the record if it's older than a week
return true
}
rec := ReplicationRecord{
rec := &discosrv.ReplicationRecord{
Key: key[:],
Addresses: value.Addresses,
Seen: value.Seen,
}
s := rec.Size()
s := proto.Size(rec)
if s+4 > len(buf) {
buf = make([]byte, s+4)
}
n, err := rec.MarshalTo(buf[4:])
n, err := protoutil.MarshalTo(buf[4:], rec)
if err != nil {
rangeErr = err
return false
@@ -349,8 +351,8 @@ func (s *inMemoryStore) read() (int, error) {
if _, err := io.ReadFull(br, buf[:n]); err != nil {
return nr, err
}
rec := ReplicationRecord{}
if err := rec.Unmarshal(buf[:n]); err != nil {
rec := &discosrv.ReplicationRecord{}
if err := proto.Unmarshal(buf[:n], rec); err != nil {
return nr, err
}
key, err := protocol.DeviceIDFromBytes(rec.Key)
@@ -362,9 +364,9 @@ func (s *inMemoryStore) read() (int, error) {
continue
}
slices.SortFunc(rec.Addresses, DatabaseAddress.Cmp)
rec.Addresses = slices.CompactFunc(rec.Addresses, DatabaseAddress.Equal)
s.m.Store(key, DatabaseRecord{
slices.SortFunc(rec.Addresses, Cmp)
rec.Addresses = slices.CompactFunc(rec.Addresses, Equal)
s.m.Store(key, &discosrv.DatabaseRecord{
Addresses: expire(rec.Addresses, s.clock.Now()),
Seen: rec.Seen,
})
@@ -377,7 +379,7 @@ func (s *inMemoryStore) read() (int, error) {
// result is the union of the two address sets, with the newer expiry time
// chosen for any duplicates. The address list in a is overwritten and
// reused for the result.
func merge(a, b DatabaseRecord) DatabaseRecord {
func merge(a, b *discosrv.DatabaseRecord) *discosrv.DatabaseRecord {
// Both lists must be sorted for this to work.
a.Seen = max(a.Seen, b.Seen)
@@ -396,7 +398,7 @@ func merge(a, b DatabaseRecord) DatabaseRecord {
aIdx++
case 1:
// a > b, insert b before a
a.Addresses = append(a.Addresses[:aIdx], append([]DatabaseAddress{b.Addresses[bIdx]}, a.Addresses[aIdx:]...)...)
a.Addresses = append(a.Addresses[:aIdx], append([]*discosrv.DatabaseAddress{b.Addresses[bIdx]}, a.Addresses[aIdx:]...)...)
bIdx++
}
}
@@ -410,7 +412,7 @@ func merge(a, b DatabaseRecord) DatabaseRecord {
// expire returns the list of addresses after removing expired entries.
// Expiration happen in place, so the slice given as the parameter is
// destroyed. Internal order is preserved.
func expire(addrs []DatabaseAddress, now time.Time) []DatabaseAddress {
func expire(addrs []*discosrv.DatabaseAddress, now time.Time) []*discosrv.DatabaseAddress {
cutoff := now.UnixNano()
naddrs := addrs[:0]
for i := range addrs {
@@ -428,13 +430,13 @@ func expire(addrs []DatabaseAddress, now time.Time) []DatabaseAddress {
return naddrs
}
func (d DatabaseAddress) Cmp(other DatabaseAddress) (n int) {
func Cmp(d, other *discosrv.DatabaseAddress) (n int) {
if c := cmp.Compare(d.Address, other.Address); c != 0 {
return c
}
return cmp.Compare(d.Expires, other.Expires)
}
func (d DatabaseAddress) Equal(other DatabaseAddress) bool {
func Equal(d, other *discosrv.DatabaseAddress) bool {
return d.Address == other.Address
}

View File

@@ -1,792 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: database.proto
package main
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type DatabaseRecord struct {
Addresses []DatabaseAddress `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses"`
Seen int64 `protobuf:"varint,3,opt,name=seen,proto3" json:"seen,omitempty"`
}
func (m *DatabaseRecord) Reset() { *m = DatabaseRecord{} }
func (m *DatabaseRecord) String() string { return proto.CompactTextString(m) }
func (*DatabaseRecord) ProtoMessage() {}
func (*DatabaseRecord) Descriptor() ([]byte, []int) {
return fileDescriptor_b90fe3356ea5df07, []int{0}
}
func (m *DatabaseRecord) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *DatabaseRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_DatabaseRecord.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *DatabaseRecord) XXX_Merge(src proto.Message) {
xxx_messageInfo_DatabaseRecord.Merge(m, src)
}
func (m *DatabaseRecord) XXX_Size() int {
return m.Size()
}
func (m *DatabaseRecord) XXX_DiscardUnknown() {
xxx_messageInfo_DatabaseRecord.DiscardUnknown(m)
}
var xxx_messageInfo_DatabaseRecord proto.InternalMessageInfo
type ReplicationRecord struct {
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Addresses []DatabaseAddress `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses"`
Seen int64 `protobuf:"varint,3,opt,name=seen,proto3" json:"seen,omitempty"`
}
func (m *ReplicationRecord) Reset() { *m = ReplicationRecord{} }
func (m *ReplicationRecord) String() string { return proto.CompactTextString(m) }
func (*ReplicationRecord) ProtoMessage() {}
func (*ReplicationRecord) Descriptor() ([]byte, []int) {
return fileDescriptor_b90fe3356ea5df07, []int{1}
}
func (m *ReplicationRecord) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ReplicationRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ReplicationRecord.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ReplicationRecord) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReplicationRecord.Merge(m, src)
}
func (m *ReplicationRecord) XXX_Size() int {
return m.Size()
}
func (m *ReplicationRecord) XXX_DiscardUnknown() {
xxx_messageInfo_ReplicationRecord.DiscardUnknown(m)
}
var xxx_messageInfo_ReplicationRecord proto.InternalMessageInfo
type DatabaseAddress struct {
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
Expires int64 `protobuf:"varint,2,opt,name=expires,proto3" json:"expires,omitempty"`
}
func (m *DatabaseAddress) Reset() { *m = DatabaseAddress{} }
func (m *DatabaseAddress) String() string { return proto.CompactTextString(m) }
func (*DatabaseAddress) ProtoMessage() {}
func (*DatabaseAddress) Descriptor() ([]byte, []int) {
return fileDescriptor_b90fe3356ea5df07, []int{2}
}
func (m *DatabaseAddress) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *DatabaseAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_DatabaseAddress.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *DatabaseAddress) XXX_Merge(src proto.Message) {
xxx_messageInfo_DatabaseAddress.Merge(m, src)
}
func (m *DatabaseAddress) XXX_Size() int {
return m.Size()
}
func (m *DatabaseAddress) XXX_DiscardUnknown() {
xxx_messageInfo_DatabaseAddress.DiscardUnknown(m)
}
var xxx_messageInfo_DatabaseAddress proto.InternalMessageInfo
func init() {
proto.RegisterType((*DatabaseRecord)(nil), "main.DatabaseRecord")
proto.RegisterType((*ReplicationRecord)(nil), "main.ReplicationRecord")
proto.RegisterType((*DatabaseAddress)(nil), "main.DatabaseAddress")
}
func init() { proto.RegisterFile("database.proto", fileDescriptor_b90fe3356ea5df07) }
var fileDescriptor_b90fe3356ea5df07 = []byte{
// 243 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4b, 0x49, 0x2c, 0x49,
0x4c, 0x4a, 0x2c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xc9, 0x4d, 0xcc, 0xcc,
0x93, 0x52, 0x2e, 0x4a, 0x2d, 0xc8, 0x2f, 0xd6, 0x07, 0x0b, 0x25, 0x95, 0xa6, 0xe9, 0xa7, 0xe7,
0xa7, 0xe7, 0x83, 0x39, 0x60, 0x16, 0x44, 0xa9, 0x52, 0x3c, 0x17, 0x9f, 0x0b, 0x54, 0x73, 0x50,
0x6a, 0x72, 0x7e, 0x51, 0x8a, 0x90, 0x25, 0x17, 0x67, 0x62, 0x4a, 0x4a, 0x51, 0x6a, 0x71, 0x71,
0x6a, 0xb1, 0x04, 0xa3, 0x02, 0xb3, 0x06, 0xb7, 0x91, 0xa8, 0x1e, 0xc8, 0x40, 0x3d, 0x98, 0x42,
0x47, 0x88, 0xb4, 0x13, 0xcb, 0x89, 0x7b, 0xf2, 0x0c, 0x41, 0x08, 0xd5, 0x42, 0x42, 0x5c, 0x2c,
0xc5, 0xa9, 0xa9, 0x79, 0x12, 0xcc, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x60, 0xb6, 0x52, 0x09, 0x97,
0x60, 0x50, 0x6a, 0x41, 0x4e, 0x66, 0x72, 0x62, 0x49, 0x66, 0x7e, 0x1e, 0xd4, 0x0e, 0x01, 0x2e,
0xe6, 0xec, 0xd4, 0x4a, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x10, 0x13, 0xd5, 0x56, 0x26,
0x8a, 0x6d, 0x75, 0xe5, 0xe2, 0x47, 0xd3, 0x27, 0x24, 0xc1, 0xc5, 0x0e, 0xd5, 0x03, 0xb6, 0x97,
0x33, 0x08, 0xc6, 0x05, 0xc9, 0xa4, 0x56, 0x14, 0x64, 0x16, 0x81, 0x6d, 0x06, 0x99, 0x01, 0xe3,
0x3a, 0xc9, 0x9c, 0x78, 0x28, 0xc7, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f,
0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c,
0x49, 0x6c, 0xe0, 0x20, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x0b, 0x9b, 0x77, 0x7f,
0x01, 0x00, 0x00,
}
func (m *DatabaseRecord) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *DatabaseRecord) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *DatabaseRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Seen != 0 {
i = encodeVarintDatabase(dAtA, i, uint64(m.Seen))
i--
dAtA[i] = 0x18
}
if len(m.Addresses) > 0 {
for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Addresses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintDatabase(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func (m *ReplicationRecord) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ReplicationRecord) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ReplicationRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Seen != 0 {
i = encodeVarintDatabase(dAtA, i, uint64(m.Seen))
i--
dAtA[i] = 0x18
}
if len(m.Addresses) > 0 {
for iNdEx := len(m.Addresses) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Addresses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintDatabase(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
}
if len(m.Key) > 0 {
i -= len(m.Key)
copy(dAtA[i:], m.Key)
i = encodeVarintDatabase(dAtA, i, uint64(len(m.Key)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *DatabaseAddress) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *DatabaseAddress) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *DatabaseAddress) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Expires != 0 {
i = encodeVarintDatabase(dAtA, i, uint64(m.Expires))
i--
dAtA[i] = 0x10
}
if len(m.Address) > 0 {
i -= len(m.Address)
copy(dAtA[i:], m.Address)
i = encodeVarintDatabase(dAtA, i, uint64(len(m.Address)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintDatabase(dAtA []byte, offset int, v uint64) int {
offset -= sovDatabase(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *DatabaseRecord) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Addresses) > 0 {
for _, e := range m.Addresses {
l = e.Size()
n += 1 + l + sovDatabase(uint64(l))
}
}
if m.Seen != 0 {
n += 1 + sovDatabase(uint64(m.Seen))
}
return n
}
func (m *ReplicationRecord) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Key)
if l > 0 {
n += 1 + l + sovDatabase(uint64(l))
}
if len(m.Addresses) > 0 {
for _, e := range m.Addresses {
l = e.Size()
n += 1 + l + sovDatabase(uint64(l))
}
}
if m.Seen != 0 {
n += 1 + sovDatabase(uint64(m.Seen))
}
return n
}
func (m *DatabaseAddress) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Address)
if l > 0 {
n += 1 + l + sovDatabase(uint64(l))
}
if m.Expires != 0 {
n += 1 + sovDatabase(uint64(m.Expires))
}
return n
}
func sovDatabase(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozDatabase(x uint64) (n int) {
return sovDatabase(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *DatabaseRecord) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: DatabaseRecord: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: DatabaseRecord: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthDatabase
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthDatabase
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Addresses = append(m.Addresses, DatabaseAddress{})
if err := m.Addresses[len(m.Addresses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Seen", wireType)
}
m.Seen = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Seen |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipDatabase(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthDatabase
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ReplicationRecord) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ReplicationRecord: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ReplicationRecord: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthDatabase
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthDatabase
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthDatabase
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthDatabase
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Addresses = append(m.Addresses, DatabaseAddress{})
if err := m.Addresses[len(m.Addresses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Seen", wireType)
}
m.Seen = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Seen |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipDatabase(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthDatabase
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *DatabaseAddress) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: DatabaseAddress: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: DatabaseAddress: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthDatabase
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthDatabase
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Address = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Expires", wireType)
}
m.Expires = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDatabase
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Expires |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipDatabase(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthDatabase
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipDatabase(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowDatabase
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowDatabase
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowDatabase
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthDatabase
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupDatabase
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthDatabase
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthDatabase = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowDatabase = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupDatabase = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -1,32 +0,0 @@
// Copyright (C) 2018 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
syntax = "proto3";
package main;
import "repos/protobuf/gogoproto/gogo.proto";
option (gogoproto.goproto_getters_all) = false;
option (gogoproto.goproto_unkeyed_all) = false;
option (gogoproto.goproto_unrecognized_all) = false;
option (gogoproto.goproto_sizecache_all) = false;
message DatabaseRecord {
repeated DatabaseAddress addresses = 1 [(gogoproto.nullable) = false];
int64 seen = 3; // Unix nanos, last device announce
}
message ReplicationRecord {
bytes key = 1; // raw 32 byte device ID
repeated DatabaseAddress addresses = 2 [(gogoproto.nullable) = false];
int64 seen = 3; // Unix nanos, last device announce
}
message DatabaseAddress {
string address = 1;
int64 expires = 2; // Unix nanos
}

View File

@@ -12,6 +12,7 @@ import (
"testing"
"time"
"github.com/syncthing/syncthing/internal/gen/discosrv"
"github.com/syncthing/syncthing/lib/protocol"
)
@@ -39,7 +40,7 @@ func TestDatabaseGetSet(t *testing.T) {
// Put a record
rec.Addresses = []DatabaseAddress{
rec.Addresses = []*discosrv.DatabaseAddress{
{Address: "tcp://1.2.3.4:5", Expires: tc.Now().Add(time.Minute).UnixNano()},
}
if err := db.put(&protocol.EmptyDeviceID, rec); err != nil {
@@ -65,7 +66,7 @@ func TestDatabaseGetSet(t *testing.T) {
tc.wind(30 * time.Second)
addrs := []DatabaseAddress{
addrs := []*discosrv.DatabaseAddress{
{Address: "tcp://6.7.8.9:0", Expires: tc.Now().Add(time.Minute).UnixNano()},
}
if err := db.merge(&protocol.EmptyDeviceID, addrs, tc.Now().UnixNano()); err != nil {
@@ -112,7 +113,7 @@ func TestDatabaseGetSet(t *testing.T) {
// Set an address
addrs = []DatabaseAddress{
addrs = []*discosrv.DatabaseAddress{
{Address: "tcp://6.7.8.9:0", Expires: tc.Now().Add(time.Minute).UnixNano()},
}
if err := db.merge(&protocol.GlobalDeviceID, addrs, tc.Now().UnixNano()); err != nil {
@@ -134,28 +135,28 @@ func TestDatabaseGetSet(t *testing.T) {
func TestFilter(t *testing.T) {
// all cases are expired with t=10
cases := []struct {
a []DatabaseAddress
b []DatabaseAddress
a []*discosrv.DatabaseAddress
b []*discosrv.DatabaseAddress
}{
{
a: nil,
b: nil,
},
{
a: []DatabaseAddress{{Address: "a", Expires: 9}, {Address: "b", Expires: 9}, {Address: "c", Expires: 9}},
b: []DatabaseAddress{},
a: []*discosrv.DatabaseAddress{{Address: "a", Expires: 9}, {Address: "b", Expires: 9}, {Address: "c", Expires: 9}},
b: []*discosrv.DatabaseAddress{},
},
{
a: []DatabaseAddress{{Address: "a", Expires: 10}},
b: []DatabaseAddress{{Address: "a", Expires: 10}},
a: []*discosrv.DatabaseAddress{{Address: "a", Expires: 10}},
b: []*discosrv.DatabaseAddress{{Address: "a", Expires: 10}},
},
{
a: []DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
b: []DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
a: []*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
b: []*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
},
{
a: []DatabaseAddress{{Address: "a", Expires: 5}, {Address: "b", Expires: 15}, {Address: "c", Expires: 5}, {Address: "d", Expires: 15}, {Address: "e", Expires: 5}},
b: []DatabaseAddress{{Address: "b", Expires: 15}, {Address: "d", Expires: 15}},
a: []*discosrv.DatabaseAddress{{Address: "a", Expires: 5}, {Address: "b", Expires: 15}, {Address: "c", Expires: 5}, {Address: "d", Expires: 15}, {Address: "e", Expires: 5}},
b: []*discosrv.DatabaseAddress{{Address: "b", Expires: 15}, {Address: "d", Expires: 15}},
},
}
@@ -169,62 +170,62 @@ func TestFilter(t *testing.T) {
func TestMerge(t *testing.T) {
cases := []struct {
a, b, res []DatabaseAddress
a, b, res []*discosrv.DatabaseAddress
}{
{nil, nil, nil},
{
nil,
[]DatabaseAddress{{Address: "a", Expires: 10}},
[]DatabaseAddress{{Address: "a", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}},
},
{
nil,
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
},
{
[]DatabaseAddress{{Address: "a", Expires: 10}},
[]DatabaseAddress{{Address: "a", Expires: 15}},
[]DatabaseAddress{{Address: "a", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 15}},
},
{
[]DatabaseAddress{{Address: "a", Expires: 10}},
[]DatabaseAddress{{Address: "b", Expires: 15}},
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "b", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}},
},
{
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}},
[]DatabaseAddress{{Address: "a", Expires: 15}, {Address: "b", Expires: 15}},
[]DatabaseAddress{{Address: "a", Expires: 15}, {Address: "b", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 15}, {Address: "b", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 15}, {Address: "b", Expires: 15}},
},
{
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}},
[]DatabaseAddress{{Address: "b", Expires: 15}, {Address: "c", Expires: 20}},
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}, {Address: "c", Expires: 20}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "b", Expires: 15}, {Address: "c", Expires: 20}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}, {Address: "c", Expires: 20}},
},
{
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}},
[]DatabaseAddress{{Address: "b", Expires: 5}, {Address: "c", Expires: 20}},
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}, {Address: "c", Expires: 20}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "b", Expires: 5}, {Address: "c", Expires: 20}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}, {Address: "c", Expires: 20}},
},
{
[]DatabaseAddress{{Address: "y", Expires: 10}, {Address: "z", Expires: 10}},
[]DatabaseAddress{{Address: "a", Expires: 5}, {Address: "b", Expires: 15}},
[]DatabaseAddress{{Address: "a", Expires: 5}, {Address: "b", Expires: 15}, {Address: "y", Expires: 10}, {Address: "z", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "y", Expires: 10}, {Address: "z", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 5}, {Address: "b", Expires: 15}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 5}, {Address: "b", Expires: 15}, {Address: "y", Expires: 10}, {Address: "z", Expires: 10}},
},
{
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}, {Address: "d", Expires: 10}},
[]DatabaseAddress{{Address: "b", Expires: 5}, {Address: "c", Expires: 20}},
[]DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}, {Address: "c", Expires: 20}, {Address: "d", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}, {Address: "d", Expires: 10}},
[]*discosrv.DatabaseAddress{{Address: "b", Expires: 5}, {Address: "c", Expires: 20}},
[]*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}, {Address: "c", Expires: 20}, {Address: "d", Expires: 10}},
},
}
for _, tc := range cases {
rec := merge(DatabaseRecord{Addresses: tc.a}, DatabaseRecord{Addresses: tc.b})
rec := merge(&discosrv.DatabaseRecord{Addresses: tc.a}, &discosrv.DatabaseRecord{Addresses: tc.b})
if fmt.Sprint(rec.Addresses) != fmt.Sprint(tc.res) {
t.Errorf("Incorrect result %v, expected %v", rec.Addresses, tc.res)
}
rec = merge(DatabaseRecord{Addresses: tc.b}, DatabaseRecord{Addresses: tc.a})
rec = merge(&discosrv.DatabaseRecord{Addresses: tc.b}, &discosrv.DatabaseRecord{Addresses: tc.a})
if fmt.Sprint(rec.Addresses) != fmt.Sprint(tc.res) {
t.Errorf("Incorrect result %v, expected %v", rec.Addresses, tc.res)
}
@@ -233,9 +234,9 @@ func TestMerge(t *testing.T) {
func BenchmarkMergeEqual(b *testing.B) {
for i := 0; i < b.N; i++ {
ar := []DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}}
br := []DatabaseAddress{{Address: "a", Expires: 15}, {Address: "b", Expires: 10}}
res := merge(DatabaseRecord{Addresses: ar}, DatabaseRecord{Addresses: br})
ar := []*discosrv.DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 15}}
br := []*discosrv.DatabaseAddress{{Address: "a", Expires: 15}, {Address: "b", Expires: 10}}
res := merge(&discosrv.DatabaseRecord{Addresses: ar}, &discosrv.DatabaseRecord{Addresses: br})
if len(res.Addresses) != 2 {
b.Fatal("wrong length")
}

View File

@@ -11,22 +11,22 @@ import (
"crypto/tls"
"log"
"net/http"
_ "net/http/pprof"
"os"
"os/signal"
"runtime"
"time"
_ "net/http/pprof"
"github.com/alecthomas/kong"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/thejerf/suture/v4"
_ "github.com/syncthing/syncthing/lib/automaxprocs"
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/s3"
"github.com/syncthing/syncthing/lib/tlsutil"
"github.com/thejerf/suture/v4"
)
const (

View File

@@ -12,9 +12,8 @@ import (
"time"
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/tlsutil"
"github.com/syncthing/syncthing/lib/relay/protocol"
"github.com/syncthing/syncthing/lib/tlsutil"
)
var (

View File

@@ -19,6 +19,8 @@ import (
"syscall"
"time"
"golang.org/x/time/rate"
_ "github.com/syncthing/syncthing/lib/automaxprocs"
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/config"
@@ -30,7 +32,6 @@ import (
"github.com/syncthing/syncthing/lib/relay/protocol"
"github.com/syncthing/syncthing/lib/tlsutil"
_ "github.com/syncthing/syncthing/lib/upnp"
"golang.org/x/time/rate"
)
var (

View File

@@ -68,7 +68,6 @@ func findSession(key string) *session {
ses, ok := pendingSessions[key]
if !ok {
return nil
}
delete(pendingSessions, key)
return ses

View File

@@ -11,6 +11,10 @@ import (
"fmt"
"time"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/bep"
"github.com/syncthing/syncthing/internal/gen/dbproto"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/protocol"
)
@@ -33,19 +37,19 @@ func indexDump() error {
name := nulString(key[1+4+4:])
fmt.Printf("[device] F:%d D:%d N:%q", folder, device, name)
var f protocol.FileInfo
err := f.Unmarshal(it.Value())
var f bep.FileInfo
err := proto.Unmarshal(it.Value(), &f)
if err != nil {
return err
}
fmt.Printf(" V:%v\n", f)
fmt.Printf(" V:%v\n", &f)
case db.KeyTypeGlobal:
folder := binary.BigEndian.Uint32(key[1:])
name := nulString(key[1+4:])
var flv db.VersionList
flv.Unmarshal(it.Value())
fmt.Printf("[global] F:%d N:%q V:%s\n", folder, name, flv)
var flv dbproto.VersionList
proto.Unmarshal(it.Value(), &flv)
fmt.Printf("[global] F:%d N:%q V:%s\n", folder, name, &flv)
case db.KeyTypeBlock:
folder := binary.BigEndian.Uint32(key[1:])
@@ -94,11 +98,11 @@ func indexDump() error {
case db.KeyTypeFolderMeta:
folder := binary.BigEndian.Uint32(key[1:])
fmt.Printf("[foldermeta] F:%d", folder)
var cs db.CountsSet
if err := cs.Unmarshal(it.Value()); err != nil {
var cs dbproto.CountsSet
if err := proto.Unmarshal(it.Value(), &cs); err != nil {
fmt.Printf(" (invalid)\n")
} else {
fmt.Printf(" V:%v\n", cs)
fmt.Printf(" V:%v\n", &cs)
}
case db.KeyTypeMiscData:
@@ -125,20 +129,20 @@ func indexDump() error {
case db.KeyTypeVersion:
fmt.Printf("[version] H:%x", key[1:])
var v protocol.Vector
err := v.Unmarshal(it.Value())
var v bep.Vector
err := proto.Unmarshal(it.Value(), &v)
if err != nil {
fmt.Printf(" (invalid)\n")
} else {
fmt.Printf(" V:%v\n", v)
fmt.Printf(" V:%v\n", &v)
}
case db.KeyTypePendingFolder:
device := binary.BigEndian.Uint32(key[1:])
folder := string(key[5:])
var of db.ObservedFolder
of.Unmarshal(it.Value())
fmt.Printf("[pendingFolder] D:%d F:%s V:%v\n", device, folder, of)
var of dbproto.ObservedFolder
proto.Unmarshal(it.Value(), &of)
fmt.Printf("[pendingFolder] D:%d F:%s V:%v\n", device, folder, &of)
case db.KeyTypePendingDevice:
device := "<invalid>"
@@ -146,9 +150,9 @@ func indexDump() error {
if err == nil {
device = dev.String()
}
var od db.ObservedDevice
od.Unmarshal(it.Value())
fmt.Printf("[pendingDevice] D:%v V:%v\n", device, od)
var od dbproto.ObservedDevice
proto.Unmarshal(it.Value(), &od)
fmt.Printf("[pendingDevice] D:%v V:%v\n", device, &od)
default:
fmt.Printf("[??? %d]\n %x\n %x\n", key[0], key, it.Value())

View File

@@ -13,6 +13,10 @@ import (
"fmt"
"sort"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/bep"
"github.com/syncthing/syncthing/internal/gen/dbproto"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/protocol"
)
@@ -42,12 +46,12 @@ func indexCheck() (err error) {
folders := make(map[uint32]string)
devices := make(map[uint32]string)
deviceToIDs := make(map[string]uint32)
fileInfos := make(map[fileInfoKey]protocol.FileInfo)
globals := make(map[globalKey]db.VersionList)
fileInfos := make(map[fileInfoKey]*bep.FileInfo)
globals := make(map[globalKey]*dbproto.VersionList)
sequences := make(map[sequenceKey]string)
needs := make(map[globalKey]struct{})
blocklists := make(map[string]struct{})
versions := make(map[string]protocol.Vector)
versions := make(map[string]*bep.Vector)
usedBlocklists := make(map[string]struct{})
usedVersions := make(map[string]struct{})
var localDeviceKey uint32
@@ -74,26 +78,26 @@ func indexCheck() (err error) {
device := binary.BigEndian.Uint32(key[1+4:])
name := nulString(key[1+4+4:])
var f protocol.FileInfo
err := f.Unmarshal(it.Value())
var f bep.FileInfo
err := proto.Unmarshal(it.Value(), &f)
if err != nil {
fmt.Println("Unable to unmarshal FileInfo:", err)
success = false
continue
}
fileInfos[fileInfoKey{folder, device, name}] = f
fileInfos[fileInfoKey{folder, device, name}] = &f
case db.KeyTypeGlobal:
folder := binary.BigEndian.Uint32(key[1:])
name := nulString(key[1+4:])
var flv db.VersionList
if err := flv.Unmarshal(it.Value()); err != nil {
var flv dbproto.VersionList
if err := proto.Unmarshal(it.Value(), &flv); err != nil {
fmt.Println("Unable to unmarshal VersionList:", err)
success = false
continue
}
globals[globalKey{folder, name}] = flv
globals[globalKey{folder, name}] = &flv
case db.KeyTypeFolderIdx:
key := binary.BigEndian.Uint32(it.Key()[1:])
@@ -124,13 +128,13 @@ func indexCheck() (err error) {
case db.KeyTypeVersion:
hash := string(key[1:])
var v protocol.Vector
if err := v.Unmarshal(it.Value()); err != nil {
var v bep.Vector
if err := proto.Unmarshal(it.Value(), &v); err != nil {
fmt.Println("Unable to unmarshal Vector:", err)
success = false
continue
}
versions[hash] = v
versions[hash] = &v
}
}
@@ -248,25 +252,27 @@ func indexCheck() (err error) {
if fi.VersionHash != nil {
fiv = versions[string(fi.VersionHash)]
}
if !fiv.Equal(version) {
if !protocol.VectorFromWire(fiv).Equal(version) {
fmt.Printf("VersionList %q, folder %q, entry %d, FileInfo version mismatch, %v (VersionList) != %v (FileInfo)\n", gk.name, folder, i, version, fi.Version)
success = false
}
if fi.IsInvalid() != invalid {
fmt.Printf("VersionList %q, folder %q, entry %d, FileInfo invalid mismatch, %v (VersionList) != %v (FileInfo)\n", gk.name, folder, i, invalid, fi.IsInvalid())
ffi := protocol.FileInfoFromDB(fi)
if ffi.IsInvalid() != invalid {
fmt.Printf("VersionList %q, folder %q, entry %d, FileInfo invalid mismatch, %v (VersionList) != %v (FileInfo)\n", gk.name, folder, i, invalid, ffi.IsInvalid())
success = false
}
if fi.IsDeleted() != deleted {
fmt.Printf("VersionList %q, folder %q, entry %d, FileInfo deleted mismatch, %v (VersionList) != %v (FileInfo)\n", gk.name, folder, i, deleted, fi.IsDeleted())
if ffi.IsDeleted() != deleted {
fmt.Printf("VersionList %q, folder %q, entry %d, FileInfo deleted mismatch, %v (VersionList) != %v (FileInfo)\n", gk.name, folder, i, deleted, ffi.IsDeleted())
success = false
}
}
for i, fv := range vl.RawVersions {
for i, fv := range vl.Versions {
ver := protocol.VectorFromWire(fv.Version)
for _, device := range fv.Devices {
checkGlobal(i, device, fv.Version, false, fv.Deleted)
checkGlobal(i, device, ver, false, fv.Deleted)
}
for _, device := range fv.InvalidDevices {
checkGlobal(i, device, fv.Version, true, fv.Deleted)
checkGlobal(i, device, ver, true, fv.Deleted)
}
}
@@ -276,10 +282,10 @@ func indexCheck() (err error) {
if needsLocally(vl) {
_, ok := needs[gk]
if !ok {
fv, _ := vl.GetGlobal()
devB, _ := fv.FirstDevice()
fv, _ := vlGetGlobal(vl)
devB, _ := fvFirstDevice(fv)
dev := deviceToIDs[string(devB)]
fi := fileInfos[fileInfoKey{gk.folder, dev, gk.name}]
fi := protocol.FileInfoFromDB(fileInfos[fileInfoKey{gk.folder, dev, gk.name}])
if !fi.IsDeleted() && !fi.IsIgnored() {
fmt.Printf("Missing need entry for needed file %q, folder %q\n", gk.name, folder)
}
@@ -345,11 +351,84 @@ func indexCheck() (err error) {
return nil
}
func needsLocally(vl db.VersionList) bool {
gfv, gok := vl.GetGlobal()
func needsLocally(vl *dbproto.VersionList) bool {
gfv, gok := vlGetGlobal(vl)
if !gok { // That's weird, but we hardly need something non-existent
return false
}
fv, ok := vl.Get(protocol.LocalDeviceID[:])
return db.Need(gfv, ok, fv.Version)
fv, ok := vlGet(vl, protocol.LocalDeviceID[:])
return db.Need(gfv, ok, protocol.VectorFromWire(fv.Version))
}
// Get returns a FileVersion that contains the given device and whether it has
// been found at all.
func vlGet(vl *dbproto.VersionList, device []byte) (*dbproto.FileVersion, bool) {
_, i, _, ok := vlFindDevice(vl, device)
if !ok {
return &dbproto.FileVersion{}, false
}
return vl.Versions[i], true
}
// GetGlobal returns the current global FileVersion. The returned FileVersion
// may be invalid, if all FileVersions are invalid. Returns false only if
// VersionList is empty.
func vlGetGlobal(vl *dbproto.VersionList) (*dbproto.FileVersion, bool) {
i := vlFindGlobal(vl)
if i == -1 {
return nil, false
}
return vl.Versions[i], true
}
// findGlobal returns the first version that isn't invalid, or if all versions are
// invalid just the first version (i.e. 0) or -1, if there's no versions at all.
func vlFindGlobal(vl *dbproto.VersionList) int {
for i := range vl.Versions {
if !fvIsInvalid(vl.Versions[i]) {
return i
}
}
if len(vl.Versions) == 0 {
return -1
}
return 0
}
// findDevice returns whether the device is in InvalidVersions or Versions and
// in InvalidDevices or Devices (true for invalid), the positions in the version
// and device slices and whether it has been found at all.
func vlFindDevice(vl *dbproto.VersionList, device []byte) (bool, int, int, bool) {
for i, v := range vl.Versions {
if j := deviceIndex(v.Devices, device); j != -1 {
return false, i, j, true
}
if j := deviceIndex(v.InvalidDevices, device); j != -1 {
return true, i, j, true
}
}
return false, -1, -1, false
}
func deviceIndex(devices [][]byte, device []byte) int {
for i, dev := range devices {
if bytes.Equal(device, dev) {
return i
}
}
return -1
}
func fvFirstDevice(fv *dbproto.FileVersion) ([]byte, bool) {
if len(fv.Devices) != 0 {
return fv.Devices[0], true
}
if len(fv.InvalidDevices) != 0 {
return fv.InvalidDevices[0], true
}
return nil, false
}
func fvIsInvalid(fv *dbproto.FileVersion) bool {
return fv == nil || len(fv.Devices) == 0
}

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("main", "Main package")
)
var l = logger.DefaultLogger.NewFacility("main", "Main package")

View File

@@ -17,6 +17,9 @@ import (
"os"
"path/filepath"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/bep"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/osutil"
@@ -280,10 +283,11 @@ func loadEncryptedFileInfo(fd fs.File) (*protocol.FileInfo, error) {
return nil, err
}
var encFi protocol.FileInfo
if err := encFi.Unmarshal(trailer); err != nil {
var encFi bep.FileInfo
if err := proto.Unmarshal(trailer, &encFi); err != nil {
return nil, err
}
fi := protocol.FileInfoFromWire(&encFi)
return &encFi, nil
return &fi, nil
}

View File

@@ -30,7 +30,6 @@ import (
"time"
"github.com/alecthomas/kong"
_ "github.com/syncthing/syncthing/lib/automaxprocs"
"github.com/thejerf/suture/v4"
"github.com/willabides/kongplete"
@@ -38,6 +37,7 @@ import (
"github.com/syncthing/syncthing/cmd/syncthing/cmdutil"
"github.com/syncthing/syncthing/cmd/syncthing/decrypt"
"github.com/syncthing/syncthing/cmd/syncthing/generate"
_ "github.com/syncthing/syncthing/lib/automaxprocs"
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/db"

View File

@@ -140,7 +140,7 @@ func checkNotExist(t *testing.T, name string) {
func TestAutoClosedFile(t *testing.T) {
os.RemoveAll("_autoclose")
defer os.RemoveAll("_autoclose")
os.Mkdir("_autoclose", 0755)
os.Mkdir("_autoclose", 0o755)
file := filepath.FromSlash("_autoclose/tmp")
data := []byte("hello, world\n")

View File

@@ -26,3 +26,9 @@
darwin: "20"
linux: "2.6.32"
windows: "10.0"
- runtime: go1.24
requirements:
darwin: "20"
linux: "3.2"
windows: "10.0"

51
go.mod
View File

@@ -4,7 +4,7 @@ go 1.22.0
require (
github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f
github.com/alecthomas/kong v1.2.1
github.com/alecthomas/kong v1.6.0
github.com/aws/aws-sdk-go v1.55.5
github.com/calmh/incontainer v1.0.0
github.com/calmh/xdr v1.2.0
@@ -12,41 +12,40 @@ require (
github.com/chmduquesne/rollinghash v4.0.0+incompatible
github.com/d4l3k/messagediff v1.2.1
github.com/getsentry/raven-go v0.2.0
github.com/go-ldap/ldap/v3 v3.4.8
github.com/go-ldap/ldap/v3 v3.4.10
github.com/gobwas/glob v0.2.3
github.com/gogo/protobuf v1.3.2
github.com/greatroar/blobloom v0.8.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/jackpal/gateway v1.0.15
github.com/jackpal/gateway v1.0.16
github.com/jackpal/go-nat-pmp v1.0.2
github.com/julienschmidt/httprouter v1.3.0
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/maruel/panicparse/v2 v2.3.1
github.com/maruel/panicparse/v2 v2.4.0
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1
github.com/maxmind/geoipupdate/v6 v6.1.0
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
github.com/oschwald/geoip2-golang v1.11.0
github.com/pierrec/lz4/v4 v4.1.21
github.com/prometheus/client_golang v1.20.4
github.com/pierrec/lz4/v4 v4.1.22
github.com/prometheus/client_golang v1.20.5
github.com/puzpuzpuz/xsync/v3 v3.4.0
github.com/quic-go/quic-go v0.47.0
github.com/quic-go/quic-go v0.48.2
github.com/rabbitmq/amqp091-go v1.10.0
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
github.com/shirou/gopsutil/v4 v4.24.9
github.com/shirou/gopsutil/v4 v4.24.12
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
github.com/thejerf/suture/v4 v4.0.5
github.com/urfave/cli v1.22.15
github.com/thejerf/suture/v4 v4.0.6
github.com/urfave/cli v1.22.16
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
github.com/willabides/kongplete v0.4.0
go.uber.org/automaxprocs v1.6.0
golang.org/x/crypto v0.27.0
golang.org/x/net v0.29.0
golang.org/x/sys v0.25.0
golang.org/x/text v0.18.0
golang.org/x/time v0.6.0
golang.org/x/tools v0.25.0
google.golang.org/protobuf v1.34.2
golang.org/x/crypto v0.31.0
golang.org/x/net v0.33.0
golang.org/x/sys v0.28.0
golang.org/x/text v0.21.0
golang.org/x/time v0.8.0
golang.org/x/tools v0.28.0
google.golang.org/protobuf v1.36.1
sigs.k8s.io/yaml v1.4.0
)
@@ -58,19 +57,19 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/ebitengine/purego v0.8.0 // indirect
github.com/ebitengine/purego v0.8.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d // indirect
github.com/google/pprof v0.0.0-20241009165004-a3522334989c // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/klauspost/compress v1.17.10 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nxadm/tail v1.4.11 // indirect
@@ -86,14 +85,14 @@ require (
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/tklauser/numcpus v0.9.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/mock v0.4.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sync v0.10.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

148
go.sum
View File

@@ -2,11 +2,11 @@ github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f h1:GmH5
github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f/go.mod h1:Nhfib1j/VFnLrXL9cHgA+/n2O6P5THuWelOnbfPNd78=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZP/GkPY=
github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/kong v1.2.1 h1:E8jH4Tsgv6wCRX2nGrdPyHDUCSG83WH2qE4XLACD33Q=
github.com/alecthomas/kong v1.2.1/go.mod h1:rKTSFhbdp3Ryefn8x5MOEprnRFQ7nlmMC01GKhehhBM=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/kong v1.6.0 h1:mwOzbdMR7uv2vul9J0FU3GYxE7ls/iX1ieMg5WIM6gE=
github.com/alecthomas/kong v1.6.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
@@ -34,7 +34,6 @@ github.com/chmduquesne/rollinghash v4.0.0+incompatible/go.mod h1:Uc2I36RRfTAf7Dg
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
@@ -42,8 +41,8 @@ github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkE
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE=
github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
@@ -52,11 +51,10 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ=
github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk=
github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
@@ -67,8 +65,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@@ -84,13 +80,12 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d h1:Jaz2JzpQaQXyET0AjLBXShrthbpqMkhGiEfkcQAiAUs=
github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/pprof v0.0.0-20241009165004-a3522334989c h1:NDovD0SMpBYXlE1zJmS1q55vWB/fUQBcPAqAboZSccA=
github.com/google/pprof v0.0.0-20241009165004-a3522334989c/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
@@ -112,8 +107,8 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jackpal/gateway v1.0.15 h1:yb4Gltgr8ApHWWnSyybnDL1vURbqw7ooo7IIL5VZSeg=
github.com/jackpal/gateway v1.0.15/go.mod h1:dbyEDcDhHUh9EmjB9ung81elMUZfG0SoNc2TfTbcj4c=
github.com/jackpal/gateway v1.0.16 h1:mTBRuHSW8qviVqX7kXnxKevqlfS/OA01ys6k6fxSX7w=
github.com/jackpal/gateway v1.0.16/go.mod h1:IOn1OUbso/cGYmnCBZbCEqhNCLSz0xxdtIpUpri5/nA=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
@@ -136,10 +131,8 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4d
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -148,15 +141,12 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0=
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/maruel/panicparse/v2 v2.3.1 h1:NtJavmbMn0DyzmmSStE8yUsmPZrZmudPH7kplxBinOA=
github.com/maruel/panicparse/v2 v2.3.1/go.mod h1:s3UmQB9Fm/n7n/prcD2xBGDkwXD6y2LeZnhbEXvs9Dg=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/maruel/panicparse/v2 v2.4.0 h1:yQKMIbQ0DKfinzVkTkcUzQyQ60UCiNnYfR7PWwTs2VI=
github.com/maruel/panicparse/v2 v2.4.0/go.mod h1:nOY2OKe8csO3F3SA5+hsxot05JLgukrF54B9x88fVp4=
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 h1:NicmruxkeqHjDv03SfSxqmaLuisddudfP3h5wdXFbhM=
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I=
github.com/maxmind/geoipupdate/v6 v6.1.0 h1:sdtTHzzQNJlXF5+fd/EoPTucRHyMonYt/Cok8xzzfqA=
github.com/maxmind/geoipupdate/v6 v6.1.0/go.mod h1:cZYCDzfMzTY4v6dKRdV7KTB6SStxtn3yFkiJ1btTGGc=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 h1:cUVxyR+UfmdEAZGJ8IiKld1O0dbGotEnkMolG5hfMSY=
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75/go.mod h1:pBbZyGwC5i16IBkjVKoy/sznA8jPD/K9iedwe1ESE6w=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
@@ -183,8 +173,8 @@ github.com/oschwald/geoip2-golang v1.11.0 h1:hNENhCn1Uyzhf9PTmquXENiWS6AlxAEnBII
github.com/oschwald/geoip2-golang v1.11.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo=
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -196,8 +186,8 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
@@ -206,8 +196,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/quic-go/quic-go v0.47.0 h1:yXs3v7r2bm1wmPTYNLKAAJTHMYkPEsfYJmTazXrCZ7Y=
github.com/quic-go/quic-go v0.47.0/go.mod h1:3bCapYsJvXGZcipOHuu7plYtaV6tnF+z7wIFsU0WK9E=
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
@@ -220,8 +210,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI=
github.com/shirou/gopsutil/v4 v4.24.9/go.mod h1:3fkaHNeYsUFCGZ8+9vZVWtbyM1k2eRnlL+bWO8Bxa/Q=
github.com/shirou/gopsutil/v4 v4.24.12 h1:qvePBOk20e0IKA1QXrIIU+jmk+zEiYVVx06WjBRlZo4=
github.com/shirou/gopsutil/v4 v4.24.12/go.mod h1:DCtMPAad2XceTeIAbGyVfycbYQNBGk2P8cvDi7/VN9o=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -234,26 +224,26 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2 h1:F4snRP//nIuTTW9LYEzVH4HVwDG9T3M4t8y/2nqMbiY=
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2/go.mod h1:J0q59IWjLtpRIJulohwqEZvjzwOfTEPp8SVhDJl+y0Y=
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
github.com/thejerf/suture/v4 v4.0.5 h1:F1E/4FZwXWqvlWDKEUo6/ndLtxGAUzMmNqkrMknZbAA=
github.com/thejerf/suture/v4 v4.0.5/go.mod h1:gu9Y4dXNUWFrByqRt30Rm9/UZ0wzRSt9AJS6xu/ZGxU=
github.com/thejerf/suture/v4 v4.0.6 h1:QsuCEsCqb03xF9tPAsWAj8QOAJBgQI1c0VqJNaingg8=
github.com/thejerf/suture/v4 v4.0.6/go.mod h1:gu9Y4dXNUWFrByqRt30Rm9/UZ0wzRSt9AJS6xu/ZGxU=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo=
github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po=
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 h1:okhMind4q9H1OxF44gNegWkiP4H/gsTFLalHFa4OOUI=
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0/go.mod h1:TTbGUfE+cXXceWtbTHq6lqcTvYPBKLNejBEbnUsQJtU=
github.com/willabides/kongplete v0.4.0 h1:eivXxkp5ud5+4+NVN9e4goxC5mSh3n1RHov+gsblM2g=
github.com/willabides/kongplete v0.4.0/go.mod h1:0P0jtWD9aTsqPSUAl4de35DLghrr57XcayPyvqSi2X8=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
@@ -269,23 +259,25 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -296,18 +288,21 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -324,10 +319,7 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -335,36 +327,42 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -378,8 +376,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@@ -224,7 +224,6 @@ code.ng-binding{
}
.well, .form-control[readonly="readonly"], .popover { /* read-only fields*/
color: #666 !important;
border-color: #444 !important;
background-color: #111 !important;
}
@@ -278,3 +277,17 @@ code.ng-binding{
.reception {
filter: invert(77%) sepia(0%) saturate(724%) hue-rotate(146deg) brightness(91%) contrast(85%);
}
/* Disabled checkbox panels */
.checkbox[disabled] {
background-color: #222222;
}
.checkbox[disabled] * {
color: #666666;
}
.checkbox[disabled] .help-block {
color: #666666 !important;
}

View File

@@ -228,7 +228,6 @@ code.ng-binding{
}
.well, .form-control[readonly="readonly"], .popover { /* read-only fields*/
color: #666 !important;
border-color: #424242 !important;
background-color: #3B3B3B !important;
}
@@ -289,4 +288,18 @@ code.ng-binding{
/* Remote Devices 'connection type'-icon color set to #aaa */
.reception {
filter: invert(77%) sepia(0%) saturate(724%) hue-rotate(146deg) brightness(91%) contrast(85%);
}
}
/* Disabled checkbox panels */
.checkbox[disabled] {
background-color: #3B3B3B;
}
.checkbox[disabled] * {
color: #999999;
}
.checkbox[disabled] .help-block {
color: #999999 !important;
}

View File

@@ -448,7 +448,6 @@ ul.three-columns li, ul.two-columns li {
}
@media (max-width:479px) {
nav .dropdown-toggle {
font-size: 1em;
}
@@ -456,13 +455,7 @@ ul.three-columns li, ul.two-columns li {
.navbar-nav .open .dropdown-menu > li > a {
padding: 12px 15px 12px 25px;
}
}
.tab-content {
padding-top: 10px;
}
@media (max-width: 419px) {
/* The selectors are build to target only the content of folder and device
panels as it would "destroy" e.g. out of sync or recent changes listings.
The !important is needed to override .visible-xs that sets display to a
@@ -513,6 +506,10 @@ ul.three-columns li, ul.two-columns li {
}
}
.tab-content {
padding-top: 10px;
}
.form-horizontal .form-group {
margin-bottom: 5px;
}

View File

@@ -22,7 +22,7 @@
"Advanced Configuration": "Разширени настройки",
"All Data": "Всички данни",
"All Time": "През цялото време",
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Всички папки, споделени с устройството трябва да бъдат защитени с парола, така че данните да са недостъпни без нея.",
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Папките, споделени с устройството трябва да бъдат защитени с парола, така че данните да са недостъпни без нея.",
"Allow Anonymous Usage Reporting?": "Разрешавате ли анонимно отчитане на употребата?",
"Allowed Networks": "Разрешени мрежи",
"Alphabetic": "Азбучен ред",
@@ -111,7 +111,7 @@
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Изключено периодично обхождане и грешка при започване на наблюдението за промени, прави се опит всяка минута:",
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Изключва сравняването и синхронизацията на правата на файловете. Полезно за системи с липсващи или специфични права (като FAT, exFAT, Synology, Android).",
"Discard": "Отказване",
"Disconnected": "Не е свързано",
"Disconnected": "Няма връзка",
"Disconnected (Inactive)": "Не е свързано (неизползвано)",
"Disconnected (Unused)": "Не е свързано (неизползвано)",
"Discovered": "Открит",
@@ -134,8 +134,8 @@
"Edit Folder Defaults": "За нови папки",
"Editing {%path%}.": "Променяне на {{path}}.",
"Enable Crash Reporting": "Включване на доклад за срив",
"Enable NAT traversal": "Преминаване през NAT",
"Enable Relaying": "Препращане",
"Enable NAT traversal": "Обхождане на NAT",
"Enable Relaying": "Разрешаване на ретранслатори",
"Enabled": "Включено",
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Когато е отметнато разширените атрибути се изпращат към другите устройства, а получените разширени атрибути се прилагат. Обикновено изисква съответните за целта права.",
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Когато е отметнато разширените атрибути се изпращат към другите устройства, но получените разширени атрибути не се прилагат. Може да има значително неблагоприятно влияние върху производителността. Винаги е отметнато когато „Синхронизиране на разширени атрибути“ е отметнато.",
@@ -158,8 +158,8 @@
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Неуспешна връзка към сървъри по IPv6 може да се очаква ако няма свързаност по IPv6.",
"File Pull Order": "Ред на изтегляне",
"File Versioning": "Версии на файловете",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Файловете биват преместени в папка .stversions при заменяне или изтриване от Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Когато Syncthing замени или изтрие файл той бива преместен в папката .stversions и преименуван чрез добавяне на датата и часа.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Когато Syncthing замени или премахне файл, негова версия се копира в папка .stversions.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Когато Syncthing замени или премахне файл, негова версия се копира в папка .stversions, като в името му се добавят датата и часът.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Предпазва местните файлове от промени, идващи от другите устройства, но местните промени се изпращат.",
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Файловете се синхронизират от другите устройства, но местните промени не се изпращат.",
"Filesystem Watcher Errors": "Грешка при наблюдаване на файловата система",
@@ -205,7 +205,7 @@
"Ignored Folders": "Пренебрегнати папки",
"Ignored at": "Пренебрегнато на",
"Included Software": "Използван софтуер",
"Incoming Rate Limit (KiB/s)": "Ограничение при изтегляне (KiB/s)",
"Incoming Rate Limit (KiB/s)": "Ограничение при изтегляне (КиБ/с)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Неправилни настройки могат да повредят файлове и да попречат на синхронизирането.",
"Incorrect user name or password.": "Грешно потребителско име или парола.",
"Internally used paths:": "Вътрешно използвани пътища:",
@@ -215,7 +215,7 @@
"Inversion of the given condition (i.e. do not exclude)": "Обръща значението на условието (напр. да не се отхвърля)",
"Keep Versions": "Пазени версии",
"LDAP": "LDAP",
"Largest First": "Първо най-големи",
"Largest First": "Първо най-големите",
"Last 30 Days": "Последните 30 дена",
"Last 7 Days": "Последните 7 дена",
"Last Month": "Миналия месец",
@@ -261,7 +261,7 @@
"Never": "никога",
"New Device": "Ново устройство",
"New Folder": "Нова папка",
"Newest First": "Първо най-нови",
"Newest First": "Първо най-новите",
"No": "Не",
"No File Versioning": "Без пазене на версии",
"No files will be deleted as a result of this operation.": "В резултат на операцията няма да бъдат премахнати файлове.",
@@ -272,12 +272,12 @@
"Number of Connections": "Брой на връзките",
"OK": "Добре",
"Off": "Изключено",
"Oldest First": "Първо най-стари",
"Oldest First": "Първо най-старите",
"Optional descriptive label for the folder. Can be different on each device.": "Незадължително име на папката. Може да бъде различно на всяко устройство.",
"Options": "Настройки",
"Out of Sync": "Несинхронизирано",
"Out of Sync Items": "Несинхронизирани елементи",
"Outgoing Rate Limit (KiB/s)": "Ограничение при качване (KiB/s)",
"Outgoing Rate Limit (KiB/s)": "Ограничение при качване (КиБ/с)",
"Override": "Налагане",
"Override Changes": "Налагане на местни промени",
"Ownership": "Собственост",
@@ -307,11 +307,11 @@
"QUIC LAN": "QUIC LAN",
"QUIC WAN": "QUIC WAN",
"Quick guide to supported patterns": "Кратък наръчник на поддържаните шаблони",
"Random": "Произволен",
"Receive Encrypted": риема шифровани данни",
"Random": "В случаен ред",
"Receive Encrypted": олучава шифровани данни",
"Receive Only": "Само получава",
"Received data is already encrypted": "Получените данни вече са шифровани",
"Recent Changes": "Последни промени",
"Recent Changes": "Скорошни промени",
"Reduced by ignore patterns": "Наложени са шаблони за пренебрегване",
"Relay LAN": "Препращане по LAN",
"Relay WAN": "Препращане по WAN",
@@ -374,7 +374,7 @@
"Simple File Versioning": "Обикновени версии",
"Single level wildcard (matches within a directory only)": "Заместващ символ за едно ниво (съвпада само с папка)",
"Size": "Размер",
"Smallest First": "Първо най-малки",
"Smallest First": "Първо най-малките",
"Some discovery methods could not be established for finding other devices or announcing this device:": "Следните методи за откриване не могат да бъдат използвани за намиране на други устройства или за обявяване на това устройство, за да бъде открито от останалите:",
"Some items could not be restored:": "Някои елементи не могат да бъдат възстановени:",
"Some listening addresses could not be enabled to accept connections:": "Някои от адресите, на които Syncthing очаква връзка не могат да бъдат настроени да получават входящи връзки:",
@@ -384,7 +384,7 @@
"Stable releases only": "Само стабилни версии",
"Staggered": "Разпределени",
"Staggered File Versioning": "Разпределени версии",
"Start Browser": "Отваряне в мрежов четец",
"Start Browser": "Отваряне на мрежов четец",
"Statistics": "Статистика",
"Stay logged in": "Оставане в системата",
"Stopped": "Спряна",
@@ -437,11 +437,11 @@
"The interval must be a positive number of seconds.": "Интервалът трябва да е положителен брой секунди.",
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Интервал, в секунди, на почистване на папката с версии. Нула изключва периодичното почистване.",
"The maximum age must be a number and cannot be blank.": "Максималната възраст трябва да е число, полето не може да бъде празно.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Максимална продължителност за пазене на версия (в дни, за да не бъдат изтривани версии задайте 0).",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Максимален срок за пазене на версия (в дни, 0 без ограничение).",
"The number of connections must be a non-negative number.": "Броят на връзките трябва да бъде положително число.",
"The number of days must be a number and cannot be blank.": "Броят дни трябва да бъде число и не може да бъде празно.",
"The number of days to keep files in the trash can. Zero means forever.": "Брой дни за пазене на файловете в кошчето. Нула значи завинаги.",
"The number of old versions to keep, per file.": "Брой стари версии, които да бъдат пазени за всеки файл.",
"The number of old versions to keep, per file.": "Брой пазени стари версии на файл.",
"The number of versions must be a number and cannot be blank.": "Броят версии трябва да бъде число и не може да бъде празно.",
"The path cannot be blank.": "Пътят не може да бъде празен.",
"The rate limit is applied to the accumulated traffic of all connections to this device.": "Ограничението се прилага към общия трафик от всички връзки към това устройство.",
@@ -474,7 +474,7 @@
"Unexpected Items": "Неочаквани елементи",
"Unexpected items have been found in this folder.": "В папката са намерени неочаквани елементи.",
"Unignore": "Отменяне на пренебрегване",
"Unknown": "Неясно",
"Unknown": "Неизвестно",
"Unshared": "Несподелена",
"Unshared Devices": "Устройства, с които не е споделена",
"Unshared Folders": "Несподелени папки",
@@ -498,7 +498,7 @@
"Using a direct TCP connection over WAN": "Използване на директна свързаност с TCP през широкодостъпна мрежа",
"Version": "Издание",
"Versions": "Версии",
"Versions Path": ът до версиите",
"Versions Path": апка с версиите",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Версиите биват изтривани автоматично ако са по-стари от максималната възраст или надминават броя разрешени версии за определено време.",
"Waiting to Clean": "Изчаква за почистване",
"Waiting to Scan": "Изчаква за обхождане",

View File

@@ -221,13 +221,14 @@
"Last seen": "Naposledy spatřen",
"Latest Change": "Poslední změna",
"Learn more": "Zjistěte více",
"Learn more at {%url%}": "Více na {{url}}",
"Limit": "Limit",
"Listener Failures": "Selhání při naslouchání",
"Listener Status": "Stav naslouchání",
"Listeners": "Naslouchající",
"Loading data...": "Načítání dat…",
"Loading...": "Načítání…",
"Local Additions": "Místní příbytky",
"Local Additions": "Místní přebytky",
"Local Discovery": "Místní objevování",
"Local State": "Místní status",
"Local State (Total)": "Místní status (Celkem)",
@@ -236,11 +237,16 @@
"Log File": "Soubor logů",
"Log In": "Přihlásit se",
"Log Out": "Odhlásit se",
"Log in to see paths information.": "Pro zobrazení informací o cestě se přihlaste.",
"Log in to see version information.": "Pro zobrazení informací o verzi se přihlaste.",
"Log tailing paused. Scroll to the bottom to continue.": "Zaznamenávání událostí pozastaveno. Sjeďte dolů pro pokračování.",
"Login failed, see Syncthing logs for details.": "Přihlášení selhalo, detaily najdete v Syncthing logu.",
"Logs": "Záznamy událostí",
"Major Upgrade": "Aktualizace hlavní verze",
"Mass actions": "Hromadné akce",
"Maximum Age": "Maximální časový limit",
"Maximum single entry size": "Maximální velikost jedné položky",
"Maximum total size": "Maximální celková velikost",
"Metadata Only": "Pouze metadata",
"Minimum Free Disk Space": "Minimální velikost volného místa na úložišti",
"Mod. Device": "Zařízení, které provedlo změnu",
@@ -410,15 +416,17 @@
"The folder path cannot be blank.": "Popis umístění složky nemůže zůstat nevyplněný.",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Jsou použity následující intervaly: za první hodinu jsou ponechány verze pro každých 30 sekund, za první den jsou ponechány verze pro každou hodinu, za prvních 30 dní jsou ponechány verze pro každý den a do nejvyššího nastaveného stáří jsou ponechány verze pro každý týden.",
"The following items could not be synchronized.": "Následující položky nemohly být synchronizovány.",
"The following items were changed locally.": "Tyto položky byly změněny lokálně",
"The following items were changed locally.": "Tyto položky byly změněny lokálně.",
"The following methods are used to discover other devices on the network and announce this device to be found by others:": "K objevování ostatních zařízení a oznamování tohoto zařízení se používají následující metody:",
"The following text will automatically be inserted into a new message.": "Následující text bude automaticky vložen do nové zprávy.",
"The following unexpected items were found.": "Byly nalezeny tyto neočekávané položky.",
"The interval must be a positive number of seconds.": "Interval musí být kladný počet sekund.",
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Interval (v sekundách) pro spouštění čištění ve složce s verzemi. Nula pravidelné čištění vypíná.",
"The maximum age must be a number and cannot be blank.": "Nejvyšší stáří je třeba zadat v podobě čísla a nemůže být prázdné.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Maximální doba pro zachování verze (dny, zapsáním hodnoty 0 bude ponecháno navždy).",
"The number of days must be a number and cannot be blank.": "Je třeba, aby počet dní bylo číslo a nemůže zůstat nevyplněné.",
"The number of days to keep files in the trash can. Zero means forever.": "Počet dní, po který budou soubory uchovány v koši. Nula znamená navždy.",
"The number of connections must be a non-negative number.": "Počet spojení musí být nezáporné číslo.",
"The number of days must be a number and cannot be blank.": "Počet dní musí být číslo a nemůže zůstat nevyplněné.",
"The number of days to keep files in the trash can. Zero means forever.": "Počet dní, po které budou soubory uchovány v koši. Nula znamená navždy.",
"The number of old versions to keep, per file.": "Počet uchovávaných starších verzí každého ze souborů.",
"The number of versions must be a number and cannot be blank.": "Je třeba, aby počet verzí bylo číslo a nemůže zůstat nevyplněné.",
"The path cannot be blank.": "Popis umístění nemůže zůstat nevyplněný.",
@@ -501,6 +509,8 @@
"folder": "složka",
"full documentation": "úplná dokumentace",
"items": "položky",
"modified": "změněno",
"permit": "povolit",
"seconds": "sekund",
"theme": {
"name": {

View File

@@ -64,7 +64,7 @@
"Configuration Directory": "Konfigurationsverzeichnis",
"Configuration File": "Konfigurationsdatei",
"Configured": "Konfiguriert",
"Connected (Unused)": "Verbunden (Nicht genutzt)",
"Connected (Unused)": "Verbunden (nicht genutzt)",
"Connection Error": "Verbindungsfehler",
"Connection Management": "Verbindungsverwaltung",
"Connection Type": "Verbindungstyp",
@@ -95,7 +95,7 @@
"Deselect folders to stop sharing with this device.": "Ordner abwählen, um sie nicht mehr für mit diesem Gerät zu teilen.",
"Device": "Gerät",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Gerät „{{name}}“ ({{device}} {{address}}) möchte sich verbinden. Gerät hinzufügen?",
"Device Certificate": "Geräte-Zertifikat",
"Device Certificate": "Gerätezertifikat",
"Device ID": "Gerätekennung",
"Device Identification": "Geräteidentifikation",
"Device Name": "Gerätename",
@@ -112,8 +112,8 @@
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Deaktiviert Vergleich und Synchronisierung der Dateiberechtigungen. Dies ist hilfreich für Dateisysteme ohne konfigurierbare Berechtigungsparameter (z. B. FAT, exFAT, Synology, Android).",
"Discard": "Verwerfen",
"Disconnected": "Getrennt",
"Disconnected (Inactive)": "Getrennt (Inaktiv)",
"Disconnected (Unused)": "Getrennt (Nicht genutzt)",
"Disconnected (Inactive)": "Getrennt (inaktiv)",
"Disconnected (Unused)": "Getrennt (nicht genutzt)",
"Discovered": "Ermittelt",
"Discovery": "Gerätesuche",
"Discovery Failures": "Gerätesuchfehler",
@@ -132,7 +132,7 @@
"Edit Device Defaults": "Gerätevorgaben bearbeiten",
"Edit Folder": "Ordner bearbeiten",
"Edit Folder Defaults": "Ordnervorgaben bearbeiten",
"Editing {%path%}.": "Bearbeite {{path}}.",
"Editing {%path%}.": "Bearbeiten von {{path}}.",
"Enable Crash Reporting": "Absturzmeldung aktivieren",
"Enable NAT traversal": "NAT-Durchdringung aktivieren",
"Enable Relaying": "Weiterleitung aktivieren",
@@ -142,7 +142,7 @@
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Bewirkt das Senden der Besitzinformation an andere Geräte und das Anwenden empfangener Besitzinformation. Erfordert üblicherweise die Ausführung mit höheren Zugriffsrechten.",
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Bewirkt das Senden von Besitzinformation an andere Geräte, jedoch ohne empfangene Besitzinformation anzuwenden. Kann zu einem merklichen Leistungseinbruch führen. Immer aktiviert, wenn „Besitzinformation synchronisieren“ eingeschaltet ist.",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Geben Sie eine positive Zahl ein (z. B. „2.35“) und wählen Sie eine Einheit. Prozentsätze sind Teil der gesamten Festplattengröße.",
"Enter a non-privileged port number (1024 - 65535).": "Geben Sie eine nichtprivilegierte Portnummer ein (1024 - 65535).",
"Enter a non-privileged port number (1024 - 65535).": "Geben Sie eine nicht privilegierte Portnummer ein (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Kommagetrennte Adressen („tcp://ip:port“, „tcp://host:port“) oder „dynamic“ eingeben, um die Adresse automatisch zu ermitteln.",
"Enter ignore patterns, one per line.": "Geben Sie Ignoriermuster ein, eines pro Zeile.",
"Enter up to three octal digits.": "Tragen Sie bis zu drei oktale Ziffern ein.",
@@ -158,13 +158,13 @@
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Ein Verbindungsfehler zu IPv6-Servern ist zu erwarten, wenn es keine IPv6-Konnektivität gibt.",
"File Pull Order": "Dateiübertragungsreihenfolge",
"File Versioning": "Dateiversionierung",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Dateien werden in den .stversions Ordner verschoben, wenn sie von Syncthing ersetzt oder gelöscht wurden.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Dateien werden mit Datumsstempel versioniert und in den .stversions Ordner verschoben, wenn sie von Syncthing ersetzt oder gelöscht wurden.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Dateien werden in den Ordner .stversions verschoben, wenn sie von Syncthing ersetzt oder gelöscht wurden.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Dateien werden mit Datumsstempel versioniert und in den Ordner .stversions verschoben, wenn sie von Syncthing ersetzt oder gelöscht wurden.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Dateien sind auf diesem Gerät schreibgeschützt. Auf diesem Gerät durchgeführte Veränderungen werden aber auf den Rest des Verbunds übertragen.",
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Dateien werden vom Verbund synchronisiert, aber lokal vorgenommene Änderungen werden nicht an andere Geräte gesendet.",
"Filesystem Watcher Errors": "Fehler im Dateisystembeobachter",
"Filter by date": "Nach Datum sortieren",
"Filter by name": "Nach Name sortieren",
"Filter by name": "Nach Namen sortieren",
"Folder": "Ordner",
"Folder ID": "Ordnerkennung",
"Folder Label": "Ordnerbezeichnung",
@@ -182,9 +182,9 @@
"GUI Authentication Password": "Passwort für Zugang zur Benutzeroberfläche",
"GUI Authentication User": "Benutzername für Zugang zur Benutzeroberfläche",
"GUI Authentication: Set User and Password": "Authentifizierung für die Benutzeroberfläche: Geben Sie Benutzer und Passwort ein.",
"GUI Listen Address": "Addresse der Benutzeroberfläche",
"GUI Listen Address": "Adresse der Benutzeroberfläche",
"GUI Override Directory": "GUI-Ersatz-Verzeichnis",
"GUI Theme": "GUI Design",
"GUI Theme": "GUI-Design",
"General": "Allgemein",
"Generate": "Generieren",
"Global Discovery": "Globale Gerätesuche",
@@ -212,7 +212,7 @@
"Introduced By": "Verteilt von",
"Introducer": "Verteilergerät",
"Introduction": "Einführung",
"Inversion of the given condition (i.e. do not exclude)": "Umkehrung der angegebenen Bedingung (d. h. schließe nicht aus)",
"Inversion of the given condition (i.e. do not exclude)": "Umkehrung der angegebenen Bedingung (d. h. nicht ausschließen)",
"Keep Versions": "Versionen erhalten",
"LDAP": "LDAP",
"Largest First": "Größte zuerst",
@@ -223,7 +223,7 @@
"Last seen": "Zuletzt online",
"Latest Change": "Letzte Änderung",
"Learn more": "Mehr erfahren",
"Learn more at {%url%}": "Erfahre mehr unter {{url}}",
"Learn more at {%url%}": "Erfahren Sie mehr unter {{url}}",
"Limit": "Limit",
"Listener Failures": "Fehler bei Listener",
"Listener Status": "Status der Listener",
@@ -233,7 +233,7 @@
"Local Additions": "Lokal hinzugefügte Elemente",
"Local Discovery": "Lokale Gerätesuche",
"Local State": "Lokaler Status",
"Local State (Total)": "Lokaler Status (Gesamt)",
"Local State (Total)": "Lokaler Status (gesamt)",
"Locally Changed Items": "Lokal geänderte Elemente",
"Log": "Protokoll",
"Log File": "Protokolldatei",
@@ -283,23 +283,23 @@
"Ownership": "Besitzinformation",
"Password": "Passwort",
"Path": "Pfad",
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Pfad zum Ordner auf dem lokalen Gerät. Ordner wird erzeugt, wenn er nicht existiert. Das Tilden-Zeichen (~) kann als Abkürzung benutzt werden für",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Pfad in dem Versionen gespeichert werden sollen (leer lassen, wenn der Standard .stversions Ordner für den geteilten Ordner verwendet werden soll).",
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Pfad zum Ordner auf dem lokalen Gerät. Ordner wird erzeugt, wenn er nicht existiert. Das Tilde-Zeichen (~) kann als Abkürzung verwendet werden für",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Pfad, in dem Versionen gespeichert werden sollen (leer lassen für den Standardordner .stversions im freigegebenen Ordner).",
"Paths": "Pfade",
"Pause": "Pause",
"Pause All": "Alles pausieren",
"Paused": "Pausiert",
"Paused (Unused)": "Pausiert (Nicht genutzt)",
"Paused (Unused)": "Pausiert (nicht genutzt)",
"Pending changes": "Ausstehende Änderungen",
"Periodic scanning at given interval and disabled watching for changes": "Periodischer Scan im angegebenen Intervall und Überwachung von Änderungen deaktiviert",
"Periodic scanning at given interval and enabled watching for changes": "Periodischer Scan im angegebenen Intervall und Überwachung von Änderungen aktiviert",
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodischer Scan im angegebenen Intervall, Überwachung von Änderungen fehlgeschlagen, erneuter Versuch jede Minute:",
"Permanently add it to the ignore list, suppressing further notifications.": "Permanent zur Ignorierliste hinzufügen, um weitere Benachrichtigungen zu unterdrücken.",
"Please consult the release notes before performing a major upgrade.": "Bitte lesen Sie die Veröffentlichungshinweise bevor Sie eine Hauptversionsaktualisierung installieren.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Bitte lege einen Benutzer und ein Passwort für die Benutzeroberfläche in den Einstellungen fest.",
"Please consult the release notes before performing a major upgrade.": "Bitte lesen Sie die Veröffentlichungshinweise, bevor Sie eine Hauptversionsaktualisierung installieren.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Bitte legen Sie in den Einstellungen einen Benutzer und ein Passwort für die Benutzeroberfläche fest.",
"Please wait": "Bitte warten",
"Prefix indicating that the file can be deleted if preventing directory removal": "Präfix, das anzeigt, dass die Datei gelöscht werden kann, wenn sie die Entfernung des Ordners verhindert",
"Prefix indicating that the pattern should be matched without case sensitivity": "Präfix, das anzeigt, dass das Muster ohne Beachtung der Groß- / Kleinschreibung übereinstimmen soll",
"Prefix indicating that the pattern should be matched without case sensitivity": "Präfix, das anzeigt, dass das Muster ohne Beachtung der Groß-/Kleinschreibung abgeglichen werden soll",
"Preparing to Sync": "Vorbereiten auf die Synchronisation",
"Preview": "Vorschau",
"Preview Usage Report": "Vorschau des Nutzungsberichts",
@@ -308,7 +308,7 @@
"QUIC WAN": "QUIC WAN",
"Quick guide to supported patterns": "Schnellanleitung zu den unterstützten Mustern",
"Random": "Zufall",
"Receive Encrypted": "Empfange verschlüsselt",
"Receive Encrypted": "Verschlüsselt empfangen",
"Receive Only": "Nur empfangen",
"Received data is already encrypted": "Empfangene Daten sind bereits verschlüsselt",
"Recent Changes": "Letzte Änderungen",
@@ -362,20 +362,20 @@
"Shared With": "Geteilt mit",
"Sharing": "Teilen",
"Show ID": "Eigene Kennung",
"Show QR": "Zeige QR Code",
"Show QR": "QR-Code anzeigen",
"Show detailed discovery status": "Status der Gerätesuche anzeigen",
"Show detailed listener status": "Detaillierten Listener-Status anzeigen",
"Show diff with previous version": "Unterschied zur vorherigen Version anzeigen",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wird anstatt der Gerätekennung im Verbund-Status angezeigt. Wird als optionaler Standardname an andere Geräte bekannt gegeben.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wird auf diesem Gerät als Gerätename angezeigt und an die anderen Geräte im Geräte-Verbund weitergegeben. Wenn kein Gerätename angegeben wird, wird der Name des entfernten Gerätes genommen.",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wird anstelle der Gerätekennung im Verbundstatus angezeigt. Wird anderen Geräten als optionaler Standardname bekannt gegeben.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wird anstelle der Gerätekennung im Verbundstatus angezeigt. Wird auf den Namen aktualisiert, den das Gerät anzeigt, wenn er leer bleibt.",
"Shutdown": "Herunterfahren",
"Shutdown Complete": "Vollständig Heruntergefahren",
"Shutdown Complete": "Vollständig heruntergefahren",
"Simple": "Einfach",
"Simple File Versioning": "Einfache Dateiversionierung",
"Single level wildcard (matches within a directory only)": "Einzelnes Maskenzeichen (wird für einen einzelnen Ordner verwendet)",
"Size": "Größe",
"Smallest First": "Kleinstes zuerst",
"Some discovery methods could not be established for finding other devices or announcing this device:": "Zum Auffinden anderer Geräte, oder um dieses Gerät anzukündigen, konnten manche Methoden nicht eingerichtet werden:",
"Some discovery methods could not be established for finding other devices or announcing this device:": "Einige Erkennungsmethoden zum Auffinden anderer Geräte oder zur Meldung dieses Geräts konnten nicht eingerichtet werden:",
"Some items could not be restored:": "Einige Elemente konnten nicht wiederhergestellt werden:",
"Some listening addresses could not be enabled to accept connections:": "An manchen Netzwerkadressen kann nicht gelauscht werden, um Verbindungen anzunehmen:",
"Source Code": "Quellcode",
@@ -388,7 +388,7 @@
"Statistics": "Statistiken",
"Stay logged in": "Angemeldet bleiben",
"Stopped": "Gestoppt",
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Speichert und synchronisiert nur verschlüsselte Daten. Ordner auf allen verbundenen Geräten müssen mit dem selben Passwort eingerichtet werden oder vom Typ „{{receiveEncrypted}}“ sein.",
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Speichert und synchronisiert nur verschlüsselte Daten. Ordner auf allen verbundenen Geräten müssen mit demselben Passwort eingerichtet werden oder vom Typ „{{receiveEncrypted}}“ sein.",
"Subject:": "Betreff:",
"Support": "Support",
"Support Bundle": "Supportpaket",
@@ -396,7 +396,7 @@
"Sync Ownership": "Besitzinformation synchronisieren",
"Sync Protocol Listen Addresses": "Adresse(n) für das Synchronisierungsprotokoll",
"Sync Status": "Status der Synchronisierung",
"Syncing": "Synchronisiere",
"Syncing": "Wird synchronisiert",
"Syncthing device ID for \"{%devicename%}\"": "Syncthing-Geräte-ID für „{{devicename}}“",
"Syncthing has been shut down.": "Syncthing wurde heruntergefahren.",
"Syncthing includes the following software or portions thereof:": "Syncthing enthält die folgende Software oder Teile von:",
@@ -409,24 +409,24 @@
"Syncthing is upgrading.": "Syncthing wird aktualisiert.",
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing unterstützt jetzt automatische Absturzberichte an die Entwickler. Diese Funktion ist standardmäßig aktiviert.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing scheint nicht erreichbar zu sein oder es gibt ein Problem mit der Internetverbindung. Erneuter Versuch …",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing scheint ein Problem mit der Verarbeitung Deiner Eingabe zu haben. Bitte lade die Seite neu oder führe einen Neustart durch, falls das Problem weiterhin besteht.",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing scheint ein Problem mit der Verarbeitung Ihrer Eingabe zu haben. Laden Sie bitte die Seite neu oder führen einen Neustart durch, falls das Problem weiterhin besteht.",
"TCP LAN": "TCP LAN",
"TCP WAN": "TCP WAN",
"Take me back": "Führe mich zurück",
"Take me back": "Führen Sie mich zurück",
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Die GUI-Adresse wird durch Startoptionen überschrieben. Hier vorgenommene Änderungen werden nicht wirksam, solange die Überschreibung besteht.",
"The Syncthing Authors": "Die Syncthing-Autoren",
"The Syncthing admin interface is configured to allow remote access without a password.": "Die Syncthing-Oberfläche erlaubt mit den jetzigen Einstellungen einen Zugriff ohne Passwort.",
"The aggregated statistics are publicly available at the URL below.": "Die gesammelten Statistiken sind öffentlich unter der nachfolgenden URL verfügbar.",
"The cleanup interval cannot be blank.": "Das Bereinigungsintervall darf nicht leer sein.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Die Konfiguration wurde gespeichert, aber noch nicht aktiviert. Syncthing muss neugestartet werden, um die neue Konfiguration zu übernehmen.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Die Konfiguration wurde gespeichert, aber noch nicht aktiviert. Syncthing muss neu gestartet werden, um die neue Konfiguration zu übernehmen.",
"The device ID cannot be blank.": "Die Gerätekennung darf nicht leer sein.",
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Die hier einzutragende Gerätekennung kann im Dialog „Aktionen > Kennung anzeigen“ auf dem anderen Gerät gefunden werden. Leerzeichen und Bindestriche sind optional (werden ignoriert).",
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Der verschlüsselte Nutzungsbericht wird täglich gesendet. Er wird verwendet, um Statistiken über verwendete Betriebssysteme, Ordnergrößen und Programmversionen zu erstellen. Sollte der Bericht in Zukunft weitere Daten erfassen, wird dieses Fenster erneut angezeigt.",
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Die eingegebene Gerätekennung scheint nicht gültig zu sein. Es sollte eine 52 oder 56 stellige Zeichenkette aus Buchstaben und Nummern sein. Leerzeichen und Bindestriche sind optional.",
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Die eingegebene Gerätekennung scheint nicht gültig zu sein. Es sollte eine 52- oder 56-stellige Zeichenkette aus Buchstaben und Zahlen sein. Leerzeichen und Bindestriche sind optional.",
"The folder ID cannot be blank.": "Die Ordnerkennung darf nicht leer sein.",
"The folder ID must be unique.": "Die Ordnerkennung muss eindeutig sein.",
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Der Ordnerinhalt auf anderen Geräten wird überschrieben, um mit diesem Gerät identisch zu werden. Dateien, die hier nicht vorhanden sind, werden auf anderen Geräten gelöscht.",
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Der Ordnerinhalt auf diesem Gerät wird überschrieben, um mit anderen Geräten identisch zu werden. Dateien, die hier neu hinzugefügt wurden, werden gelöscht.",
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Der Ordnerinhalt auf diesem Gerät wird überschrieben, damit er mit anderen Geräten identisch ist. Dateien, die hier neu hinzugefügt wurden, werden gelöscht.",
"The folder path cannot be blank.": "Der Ordnerpfad darf nicht leer sein.",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Es wird in folgenden Abständen versioniert: In der ersten Stunde wird alle 30 Sekunden eine Version behalten, am ersten Tag eine jede Stunde, in den ersten 30 Tagen eine jeden Tag. Danach wird bis zum angegebenen Höchstalter eine Version pro Woche behalten.",
"The following items could not be synchronized.": "Die folgenden Elemente konnten nicht synchronisiert werden.",
@@ -435,12 +435,12 @@
"The following text will automatically be inserted into a new message.": "Der folgende Text wird automatisch in eine neue Nachricht eingefügt.",
"The following unexpected items were found.": "Die folgenden unerwarteten Elemente wurden gefunden.",
"The interval must be a positive number of seconds.": "Das Intervall muss eine positive Zahl von Sekunden sein.",
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Das Intervall, in Sekunden, zwischen den Bereinigungen im Versionsverzeichnis. Null um das regelmäßige Bereinigen zu deaktivieren.",
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Das Intervall in Sekunden zwischen den Bereinigungen im Versionsverzeichnis. Null, um das regelmäßige Bereinigen zu deaktivieren.",
"The maximum age must be a number and cannot be blank.": "Das Höchstalter muss angegeben werden und eine Zahl sein.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Die längste Zeit, die alte Versionen vorgehalten werden (in Tagen) (0 um alte Versionen für immer zu behalten).",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Die längste Zeit, die alte Versionen vorgehalten werden (in Tagen) (0, um alte Versionen für immer zu behalten).",
"The number of connections must be a non-negative number.": "Die Anzahl der Verbindungen muss eine nicht-negative Zahl sein.",
"The number of days must be a number and cannot be blank.": "Die Anzahl der Tage muss eine Ganzzahl sein und darf nicht leer sein.",
"The number of days to keep files in the trash can. Zero means forever.": "Dauer in Tagen für welche die Dateien aufgehoben werden sollen. 0 bedeutet für immer.",
"The number of days to keep files in the trash can. Zero means forever.": "Die Anzahl der Tage, die Dateien im Papierkorb verbleiben sollen. Null bedeutet für immer.",
"The number of old versions to keep, per file.": "Anzahl der alten Versionen, die von jeder Datei behalten werden sollen.",
"The number of versions must be a number and cannot be blank.": "Die Anzahl von Versionen muss eine Ganzzahl und darf nicht leer sein.",
"The path cannot be blank.": "Der Pfad darf nicht leer sein.",
@@ -456,16 +456,16 @@
"This Device": "Dieses Gerät",
"This Month": "Dieser Monat",
"This can easily give hackers access to read and change any files on your computer.": "Dies kann dazu führen, dass Unberechtigte relativ einfach auf Ihre Dateien zugreifen und diese ändern können.",
"This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.": "Dieses Gerät kann nicht automatisch andere Geräte auffinden, oder seine eigene Adresse bekannt geben, um von anderen gefunden zu werden. Nur Geräte mit statisch konfigurierten Adressen können sich verbinden.",
"This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.": "Dieses Gerät kann nicht automatisch andere Geräte auffinden oder seine eigene Adresse bekannt geben, um von anderen gefunden zu werden. Nur Geräte mit statisch konfigurierten Adressen können sich verbinden.",
"This is a major version upgrade.": "Dies ist eine Hauptversionsaktualisierung.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Diese Einstellung regelt den freien Speicherplatz, der für den Systemordner (d.h. Indexdatenbank) erforderlich ist.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Diese Einstellung regelt den freien Speicherplatz, der für den Systemordner (d. h. Indexdatenbank) erforderlich ist.",
"Time": "Zeit",
"Time the item was last modified": "Zeit der letzten Änderung des Elements",
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "Um sich mit dem Syncthing-Gerät namens „{{devicename}}“ zu verbinden, fügen Sie ein neues Gerät mit dieser ID hinzu:",
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Zum Erlauben einer Regel Häkchen setzen. Zum Verweigern einer Regel frei lassen.",
"Today": "Heute",
"Trash Can": "Papierkorb",
"Trash Can File Versioning": "Papierkorb Dateiversionierung",
"Trash Can File Versioning": "Papierkorb-Dateiversionierung",
"Type": "Typ",
"UNIX Permissions": "UNIX-Berechtigungen",
"Unavailable": "Nicht verfügbar",
@@ -491,7 +491,7 @@
"Use notifications from the filesystem to detect changed items.": "Benachrichtigungen des Dateisystems nutzen, um Änderungen zu erkennen.",
"User": "Benutzer",
"User Home": "Benutzer-Stammverzeichnis",
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Benutzername / Passwort wurde für die Benutzeroberfläche nicht gesetzt. Bitte erwägen Sie dies einzurichten.",
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Benutzername / Passwort wurde für die Benutzeroberfläche nicht gesetzt. Bitte erwägen Sie, dies einzurichten.",
"Using a QUIC connection over LAN": "Verwendet eine QUIC-Verbindung über LAN",
"Using a QUIC connection over WAN": "Verwendet eine QUIC-Verbindung über WAN",
"Using a direct TCP connection over LAN": "Verwendet eine direkte TCP-Verbindung über LAN",
@@ -512,8 +512,8 @@
"Watch for Changes": "Änderungen überwachen",
"Watching for Changes": "Überwachung von Änderungen",
"Watching for changes discovers most changes without periodic scanning.": "Das Überwachen von Änderungen entdeckt die meisten Änderungen ohne regelmäßiges Scannen.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Beachte beim Hinzufügen eines neuen Gerätes, dass dieses Gerät auch auf den anderen Geräten hinzugefügt werden muss.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Beachte bitte beim Hinzufügen eines neuen Ordners, dass die Ordnerkennung dazu verwendet wird, Ordner zwischen Geräten zu verbinden. Die Kennung muss also auf allen Geräten gleich sein, die Groß- und Kleinschreibung muss dabei beachtet werden.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Beachten Sie beim Hinzufügen eines neuen Gerätes, dass dieses Gerät auch auf den anderen Geräten hinzugefügt werden muss.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Beachten Sie bitte beim Hinzufügen eines neuen Ordners, dass die Ordnerkennung dazu verwendet wird, Ordner zwischen Geräten zu verbinden. Die Kennung muss also auf allen Geräten gleich sein, die Groß- und Kleinschreibung muss dabei beachtet werden.",
"When set to more than one on both devices, Syncthing will attempt to establish multiple concurrent connections. If the values differ, the highest will be used. Set to zero to let Syncthing decide.": "Wenn auf beiden Geräten der Wert höher als eins eingestellt ist, versucht Syncthing, mehrere gleichzeitige Verbindungen herzustellen. Wenn die Werte unterschiedlich sind, wird der höchste Wert verwendet. Den Wert auf Null setzen, um Syncthing entscheiden zu lassen.",
"Yes": "Ja",
"Yesterday": "Gestern",
@@ -524,8 +524,8 @@
"You have no ignored devices.": "Sie haben keine ignorierten Geräte.",
"You have no ignored folders.": "Sie haben keine ignorierten Ordner.",
"You have unsaved changes. Do you really want to discard them?": "Sie haben nicht gespeicherte Änderungen. Wollen Sie diese wirklich verwerfen?",
"You must keep at least one version.": "Du musst mindestens eine Version behalten.",
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "Sie sollten nie etwas im „{{receiveEncrypted}}“ Ordner lokal ändern oder hinzufügen.",
"You must keep at least one version.": "Sie müssen zumindest eine Version behalten.",
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "Sie sollten nie etwas im Ordner „{{receiveEncrypted}}“ lokal ändern oder hinzufügen.",
"Your SMS app should open to let you choose the recipient and send it from your own number.": "Ihre SMS-App sollte sich öffnen, damit Sie den Empfänger auswählen und die Nachricht von Ihrer eigenen Nummer aus versenden können.",
"Your email app should open to let you choose the recipient and send it from your own address.": "Ihre E-Mail-App sollte sich öffnen, damit Sie den Empfänger auswählen und die Nachricht von Ihrer eigenen Adresse aus versenden können.",
"days": "Tage",

View File

@@ -1,7 +1,7 @@
{
"A device with that ID is already added.": "Nadagdag na ang device na may ganitong ID.",
"A device with that ID is already added.": "May naidagdag na device na may ganitong ding ID.",
"A negative number of days doesn't make sense.": "Walang saysay ang negatibong numero ng araw.",
"A new major version may not be compatible with previous versions.": "Maaring hindi compatible ang isang bagong major na beryson sa mga kasalukuyang bersyon.",
"A new major version may not be compatible with previous versions.": "Maaring hindi compatible ang isang bagong major na beryson sa mga nakaraang bersyon.",
"API Key": "API Key",
"About": "Tungkol sa",
"Action": "Aksyon",

View File

@@ -58,6 +58,7 @@
"Configured": "設定値",
"Connected (Unused)": "接続中 (未使用)",
"Connection Error": "接続エラー",
"Connection Management": "接続管理",
"Connection Type": "接続種別",
"Connections": "接続",
"Connections via relays might be rate limited by the relay": "中継サーバー経由の通信では、中継サーバーによる帯域制限が行われる場合があります",
@@ -86,7 +87,7 @@
"Device ID": "デバイスID",
"Device Identification": "デバイスID",
"Device Name": "デバイス名",
"Device rate limits": "デバイス速度制限",
"Device rate limits": "デバイス帯域制限",
"Device that last modified the item": "項目を最後に変更したデバイス",
"Devices": "デバイス",
"Disable Crash Reporting": "クラッシュレポートを無効にする",
@@ -220,6 +221,7 @@
"No upgrades": "アップグレードしない",
"Not shared": "非共有",
"Notice": "通知",
"Number of Connections": "接続数",
"OK": "OK",
"Off": "オフ",
"Oldest First": "古い順",
@@ -368,6 +370,7 @@
"The number of old versions to keep, per file.": "ファイルごとに古いバージョンをいくつ保持するかを指定します。",
"The number of versions must be a number and cannot be blank.": "保持するバージョン数は数値を指定してください。空欄にはできません。",
"The path cannot be blank.": "パスを入力してください。",
"The rate limit is applied to the accumulated traffic of all connections to this device.": "帯域制限は、このデバイスへのすべての接続の累計トラフィックに適用されます。",
"The rate limit must be a non-negative number (0: no limit)": "帯域制限値は0以上で指定して下さい。 (0で無制限)",
"The remote device has not accepted sharing this folder.": "接続先デバイスはこのフォルダーの共有を承諾していません。",
"The remote device has paused this folder.": "接続先デバイスはこのフォルダーを一時停止中です。",
@@ -427,6 +430,7 @@
"Watching for changes discovers most changes without periodic scanning.": "変更の監視は、定期スキャンを行わずにほとんどの変更を検出できます。",
"When adding a new device, keep in mind that this device must be added on the other side too.": "新しいデバイスを追加する際は、相手側デバイスにもこのデバイスを追加してください。",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "新しいフォルダーを追加する際、フォルダーIDはデバイス間でフォルダーの対応づけに使われることに注意してください。フォルダーIDは大文字と小文字が区別され、共有するすべてのデバイスの間で完全に一致しなくてはなりません。",
"When set to more than one on both devices, Syncthing will attempt to establish multiple concurrent connections. If the values differ, the highest will be used. Set to zero to let Syncthing decide.": "両方のデバイスで1より高い値に設定すると、Syncthingは複数同時接続を確立しようとします。値が異なる場合は、最も高い値が使用されます。Syncthingに決定させる場合は、「0」を設定します。",
"Yes": "はい",
"Yesterday": "昨日",
"You can also select one of these nearby devices:": "近くに検出された以下のデバイスの一つを選択できます。",

View File

@@ -1,5 +1,5 @@
{
"A device with that ID is already added.": "이 식별자를 가진 기기가 이미 추가되어 있습니다.",
"A device with that ID is already added.": "이 아이디를 가진 기기가 이미 추가되어 있습니다.",
"A negative number of days doesn't make sense.": "일수를 음수로 입력하는 것은 올바르지 않습니다.",
"A new major version may not be compatible with previous versions.": "새로운 주요 버전이 이전 버전들과 호환되지 않을 수 있습니다.",
"API Key": "API 키",
@@ -11,7 +11,7 @@
"Add Device": "기기 추가",
"Add Folder": "폴더 추가",
"Add Remote Device": "다른 기기 추가",
"Add devices from the introducer to our device list, for mutually shared folders.": "상호 공유 폴더에 대해 소개자의 목록에 있는 기기를 현재 기기 목록에 추가니다.",
"Add devices from the introducer to our device list, for mutually shared folders.": "상호 공유 폴더에 대해 소개자의 목록에 있는 기기를 현재 기기 목록에 추가니다.",
"Add filter entry": "필터 항목 추가",
"Add ignore patterns": "무시 양식 추가",
"Add new folder?": "새 폴더를 추가하시겠습니까?",
@@ -46,7 +46,7 @@
"Automatic upgrade now offers the choice between stable releases and release candidates.": "자동 업데이트가 안정 버전과 출시 후보 중 선택할 수 있게 변경되었습니다.",
"Automatic upgrades": "자동 업데이트",
"Automatic upgrades are always enabled for candidate releases.": "출시 후보는 자동 업데이트가 항상 활성화되어 있습니다.",
"Automatically create or share folders that this device advertises at the default path.": "이 기기가 통보하는 폴더들이 기본 경로에서 자동으로 생성 또는 공유나다.",
"Automatically create or share folders that this device advertises at the default path.": "이 기기가 통보하는 폴더 기본 경로에서 자동으로 생성 또는 공유나다.",
"Available debug logging facilities:": "사용 가능한 디버그 기록 기능:",
"Be careful!": "주의하십시오!",
"Body:": "내용:",
@@ -56,7 +56,7 @@
"Clean out after": "보관 기간",
"Cleaning Versions": "버전 정리",
"Cleanup Interval": "정리 간격",
"Click to see full identification string and QR code.": "기기 식별자 전체 및 QR 코드 보기",
"Click to see full identification string and QR code.": "기기 아이디 전체 및 QR 코드 보기",
"Close": "닫기",
"Command": "명령",
"Comment, when used at the start of a line": "주석(줄 앞에 사용할 때)",
@@ -96,8 +96,8 @@
"Device": "기기",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "\"{{name}}\" ({{device}} 기기가 {{address}}) 주소에서 접속을 요청했습니다. 새 기기를 추가하시겠습니까?",
"Device Certificate": "기기 인증서",
"Device ID": "기기 식별자",
"Device Identification": "기기 식별자",
"Device ID": "기기 아이디",
"Device Identification": "기기 아이디",
"Device Name": "기기명",
"Device Status": "기기 상태",
"Device is untrusted, enter encryption password": "신뢰하지 않는 기기입니다; 암호화 비밀번호를 입력하십시오",
@@ -166,7 +166,7 @@
"Filter by date": "날짜별 검색",
"Filter by name": "이름별 검색",
"Folder": "폴더",
"Folder ID": "폴더 식별자",
"Folder ID": "폴더 아이디",
"Folder Label": "폴더명",
"Folder Path": "폴더 경로",
"Folder Status": "폴더 상태",
@@ -194,7 +194,7 @@
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "참고: 기본값은 '거부'이면서 거부 규칙만이 발견되었습니다. '모두 허용' 규칙을 가장 마지막 자리에 추가하는 것이 좋습니다.",
"Home page": "홈페이지",
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "다만, 현재 설정에 의하면 이 기능을 활성화하고 싶지 않을 확률이 높습니다. 따라서 자동 충돌 보고를 비활성화시켰습니다.",
"Identification": "식별자",
"Identification": "아이디",
"If untrusted, enter encryption password": "신뢰하지 않으면 암호화 비밀번호를 입력하십시오",
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "현재 컴퓨터의 다른 사용자로부터 Syncthing과 이를 통한 파일 접속을 차단하려면 인증을 설정하는 것이 좋습니다.",
"Ignore": "무시",
@@ -322,7 +322,7 @@
"Remove": "제거",
"Remove Device": "기기 제거",
"Remove Folder": "폴더 제거",
"Required identifier for the folder. Must be the same on all cluster devices.": "필수로 필요한 폴더의 식별자입니다. 모든 기기에서 동일해야 합니다.",
"Required identifier for the folder. Must be the same on all cluster devices.": "필수로 필요한 폴더의 아이디입니다. 모든 기기에서 동일해야 합니다.",
"Rescan": "재탐색",
"Rescan All": "모두 재탐색",
"Rescans": "재탐색",
@@ -361,13 +361,13 @@
"Shared Folders": "공유된 폴더",
"Shared With": "공유된 기기",
"Sharing": "공유",
"Show ID": "기기 식별자 보기",
"Show ID": "기기 아이디 보기",
"Show QR": "QR 코드 보기",
"Show detailed discovery status": "탐지 현황 상세 보기",
"Show detailed listener status": "대기자 현황 상세 보기",
"Show diff with previous version": "이전 버전과의 diff 보기",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "기기 식별자를 대신해 기기 목록에서 나타납니다. 다른 기기에 선택적 기본값 이름으로 통보됩니다.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "기기 식별자를 대신해 기기 목록에서 나타납니다. 비워 둘 경우 다른 기기에서 통보받은 이름으로 갱신됩니다.",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "기기 아이디를 대신해 기기 목록에서 나타납니다. 다른 기기에 선택적 기본값 이름으로 통보됩니다.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "기기 아이디를 대신해 기기 목록에서 나타납니다. 비워 둘 경우 다른 기기에서 통보받은 이름으로 갱신됩니다.",
"Shutdown": "종료",
"Shutdown Complete": "종료 완료",
"Simple": "간단",
@@ -397,7 +397,7 @@
"Sync Protocol Listen Addresses": "동기화 규약 대기 주소",
"Sync Status": "동기화 현황",
"Syncing": "동기화",
"Syncthing device ID for \"{%devicename%}\"": "\"{{devicename}}\" 기기의 Syncthing 식별자",
"Syncthing device ID for \"{%devicename%}\"": "\"{{devicename}}\" 기기의 Syncthing 아이디",
"Syncthing has been shut down.": "Syncthing이 종료되었습니다.",
"Syncthing includes the following software or portions thereof:": "Syncthing은 다음과 같은 소프트웨어 또는 그 일부를 포함합니다.",
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing은 MPL v2.0으로 허가된 자유-오픈 소스 소프트웨어입니다.",
@@ -419,12 +419,12 @@
"The aggregated statistics are publicly available at the URL below.": "수집된 통계는 아래의 주소에서 공람할 수 있습니다.",
"The cleanup interval cannot be blank.": "정리 간격은 비워 둘 수 없습니다.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "설정이 저장되었으나 아직 활성화되지 않았습니다. 새 설정을 활성화하려면 Syncthing을 재시작하십시오.",
"The device ID cannot be blank.": "기기 식별자는 비워 둘 수 없습니다.",
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "이 자리에 입력할 기기 식별자는 다른 기기의 \"동작 > 기기 식별자 보기\"에서 찾을 수 있습니다. 공백과 하이픈은 선택적입니다(무시됩니다).",
"The device ID cannot be blank.": "기기 아이디는 비워 둘 수 없습니다.",
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "이 자리에 입력할 기기 아이디는 다른 기기의 \"동작 > 기기 아이디 보기\"에서 찾을 수 있습니다. 공백과 하이픈은 선택적입니다(무시됩니다).",
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "암호화된 사용 보고서는 매일 전송됩니다. 사용 중인 운영체제, 폴더 크기와 응용 프로그램의 버전을 추적하기 위해서입니다. 만일 보고되는 정보가 변경되면 이 알림창이 다시 표시될 예정입니다.",
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "입력한 기기 식별자가 올바르지 않습니다. 52 또는 56자의 알파벳과 숫자로 구성되어야 하며, 공백과 하이픈은 선택적입니다.",
"The folder ID cannot be blank.": "폴더 식별자는 비워 둘 수 없습니다.",
"The folder ID must be unique.": "폴더 식별자는 유일무이해야 합니다.",
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "입력한 기기 아이디가 올바르지 않습니다. 52 또는 56자의 알파벳과 숫자로 구성되어야 하며, 공백과 하이픈은 선택적입니다.",
"The folder ID cannot be blank.": "폴더 아이디는 비워 둘 수 없습니다.",
"The folder ID must be unique.": "폴더 아이디는 유일무이해야 합니다.",
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "다른 기기의 폴더 내용을 현재 기기와 동일하도록 덮어씁니다. 현재 기기에 존재하지 않는 파일은 다른 기기에서 모두 삭제됩니다.",
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "현재 기기의 폴더 내용을 다른 기기와 동일하도록 덮어씁니다. 현재 기기에서 새로 추가한 파일은 모두 삭제됩니다.",
"The folder path cannot be blank.": "폴더 경로는 비워 둘 수 없습니다.",
@@ -458,10 +458,10 @@
"This can easily give hackers access to read and change any files on your computer.": "이로 인해서는 해커들이 현재 컴퓨터의 모든 파일을 손쉽게 읽고 변경할 수 있게 됩니다.",
"This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.": "이 기기는 다른 기기를 자동으로 탐지하거나 다른 기기로부터 발견되도록 자신의 주소를 통보할 수 없습니다. 고정 주소로 설정한 기기만이 현재 기기에 접속할 수 있습니다.",
"This is a major version upgrade.": "주요 버전 업데이트입니다.",
"This setting controls the free space required on the home (i.e., index database) disk.": "이 설정은 (즉, 인스 데이터베이스) 저장 장치의 여유 공간을 관리합니다.",
"This setting controls the free space required on the home (i.e., index database) disk.": "이 설정은 시스템(즉, 인스 데이터베이스가 있는) 저장 장치의 여유 공간을 관리합니다.",
"Time": "시간",
"Time the item was last modified": "항목이 가장 최근에 수정된 시간",
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "\"{{devicename}}\" 기기와 연동하려면 아래의 식별자를 이용해 본인의 기기에서 새로운 기기를 추가하십시오.",
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "\"{{devicename}}\" 기기와 연동하려면 아래의 아이디를 이용해 본인의 기기에서 새로운 기기를 추가하십시오.",
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "규칙을 허용하려면 네모칸을 체크하십시오. 거부하려면 체크하지 마십시오.",
"Today": "오늘",
"Trash Can": "휴지통",
@@ -513,7 +513,7 @@
"Watching for Changes": "변경 항목 감시",
"Watching for changes discovers most changes without periodic scanning.": "변경 항목 감시는 주기적으로 탐색하지 않아도 대부분의 변경 항목을 탐지합니다.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "새 기기를 추가할 때는 추가한 기기에서도 현재 기기를 추가해야 합니다.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "새 폴더를 추가할 때 폴더 식별자는 기기 간에 폴더를 묶어줍니다. 대소문자가 구분되며 모든 기기에서 동일해야 합니다.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "새 폴더를 추가할 때 폴더 아이디는 기기 간에 폴더를 묶어줍니다. 대소문자가 구분되며 모든 기기에서 동일해야 합니다.",
"When set to more than one on both devices, Syncthing will attempt to establish multiple concurrent connections. If the values differ, the highest will be used. Set to zero to let Syncthing decide.": "양쪽 기기에서 둘 이상으로 설정하면 Syncthing은 여러 개의 동시 연결을 설정하려고 시도합니다. 값이 서로 다르면 가장 높은 수가 적용됩니다. Syncthing이 결정하도록 하려면 0으로 설정하십시오.",
"Yes": "예",
"Yesterday": "어제",

View File

@@ -133,20 +133,27 @@
"Edit Folder": "Rediger mappe",
"Edit Folder Defaults": "Endre mappens standardverdier",
"Editing {%path%}.": "Redigerer {{path}}.",
"Enable Crash Reporting": "Skru på krasjrapportering",
"Enable NAT traversal": "Slå på NAT-traversering",
"Enable Crash Reporting": "Aktiver krasjrapportering",
"Enable NAT traversal": "Aktiver NAT-traversering",
"Enable Relaying": "Aktiver reléforsendelse",
"Enabled": "Påskrudd",
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Gjør det mulig å sende utvidede attributter til andre enheter og bruke innkommende utvidede attributter. Kan kreve kjøring med utvidede rettigheter.",
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Aktiverer sending av utvidede egenskaper til andre enheter, men tar ikke i bruk innkommende utvidede egenskaper. Dette kan ha stor betydning for ytelsen. Alltid aktivert når \"Synkroniser utvidede egenskaper\" er aktivert.",
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Aktiverer sending av informasjon om eierskap til andre enheter, og bruker innkommende informasjon om eierskap. Krever vanligvis at det kjøres med administrative rettigheter.",
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Aktiverer sending av informasjon om eierskap til andre enheter, men bruker ikke informasjon om eierskap. Dette kan ha stor betydning for ytelsen. Alltid aktivert når \"Synkroniser eierskap\" er aktivert.",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Skriv inn et ikke-negativt nummer (f.eks. \"2.35\") og velg en enhet. Prosenter er deler av total diskstørrelse.",
"Enter a non-privileged port number (1024 - 65535).": "Skriv inn et ikke-priviligert portnummer (1024-65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Legg inn kommaseparerte (\"tcp://ip:port\", \"tcp://vert:port\") adresser eller \"dynamiske\" for å utføre automatisk oppdagelse av adressen.",
"Enter ignore patterns, one per line.": "Skriv inn mønster som skal utelates, ett per linje.",
"Enter up to three octal digits.": "Legg inn opptil tre oktale sifre.",
"Error": "Feilmelding",
"Extended Attributes": "Utvidede attributter",
"Extended Attributes Filter": "Utvidede attributters filter",
"Extended Attributes": "Utvidede egenskaper",
"Extended Attributes Filter": "Utvidede Egenskaper Filter",
"External": "Ekstern",
"External File Versioning": "Ekstern versjonskontroll",
"Failed Items": "Elementsynkronisering som har mislyktes",
"Failed to load file versions.": "Lasting av fil-versjoner feilet.",
"Failed to load ignore patterns.": "Lasting av ignorer mønstre feilet.",
"Failed to setup, retrying": "Klarte ikke å utføre oppsett, prøver igjen",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Å ikke klare å koble til IPv6-tjenere er forventet hvis det ikke er noen IPv6-tilknytning.",
"File Pull Order": "Filenes henterekkefølge",
@@ -155,6 +162,7 @@
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Filer flyttes til en datostemplet versjon i .stversions-mappa når den oppdateres eller slettes av Syncthing.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Filer er beskyttet mot endringer som er gjort på andre enheter, men endringer som er gjort på denne enheten blir sendt til resten av gruppen.",
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Filer er synkronisert fra klyngen, men lokale endringer vil ikke bli sent til andre enheter.",
"Filesystem Watcher Errors": "Filesystem Watcher Feil",
"Filter by date": "Filtrer etter dato",
"Filter by name": "Filtrer etter navn",
"Folder": "Mappe",
@@ -163,12 +171,19 @@
"Folder Path": "Mappeplassering",
"Folder Status": "Mappe status",
"Folder Type": "Mappetype",
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Mappetype {{receiveEncrypted}} kan bare bli valgt ved opprettelse av ny mappe.",
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Mappetype {{receiveEncrypted}} kan ikke bli endret etter at mappen er lagt til. Du må fjerne mappen, slette eller dekryptere dataene på disken, og legge til mappen igjen.",
"Folders": "Mapper",
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "For de følgende mappene oppsto det en feil når overvåkingen av endringer startet. Det vil bli prøvd på nytt hvert minutt, så feilen kan forsvinne raskt. Hvis feilen vedvarer, prøv å fiks det underliggende problemet, eller spør om hjelp om du ikke får det til.",
"Forever": "Evig",
"Full Rescan Interval (s)": "Intervall for fullstendig omskanning (s)",
"GUI": "grafisk brukergrensesnitt",
"GUI / API HTTPS Certificate": "GUI / API HTTPS Sertifikat",
"GUI Authentication Password": "Passord for GUI-autenisering",
"GUI Authentication User": "Bruker for GUI-autenisering",
"GUI Authentication: Set User and Password": "GUI Autentifisering: Lagre bruker og passord",
"GUI Listen Address": "Lytteadresse for grafisk brukergrensesnitt",
"GUI Override Directory": "GUI Overstyr katalog",
"GUI Theme": "GUI-tema",
"General": "Hovedinnstillinger",
"Generate": "Generer",
@@ -176,11 +191,16 @@
"Global Discovery Servers": "Globale oppdagelses servere",
"Global State": "Global tilstand",
"Help": "Hjelp",
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Hint: bare avvis-regler blir registrert når standard er avvis. Vurder å legge til \"tillat noen\" som en siste regel.",
"Home page": "Hjemmeside",
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Imdlertid indikerer dine nåværende innstillinger at du ikke vil ha det aktivert. Vi har deaktivert automatiske krasjrapporter for deg.",
"Identification": "Identifikasjon",
"If untrusted, enter encryption password": "Hvis ikke sikkert, legg til krypterings-passord",
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Hvis du vil hindre andre brukere på denne maskinen fra tilgang til Syncthing, og gjennom det dine filer, vurder å sette opp autentisering.",
"Ignore": "Ignorer",
"Ignore Patterns": "Utelatelsesmønster",
"Ignore Permissions": "Ignorer rettigheter",
"Ignore patterns can only be added after the folder is created. If checked, an input field to enter ignore patterns will be presented after saving.": "Ignonrer-mønstre kan bare bli lagt til etter at mappen er opprettet. Om du har krysset av vil du blir spurt om å fylle inn ignorer-mønster etter at du har lagret.",
"Ignored Devices": "Ignorerte enheter",
"Ignored Folders": "Utelatte mapper",
"Ignored at": "Ignorert i",
@@ -188,6 +208,7 @@
"Incoming Rate Limit (KiB/s)": "Innkommende hastighetsbegrensning (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Feilaktige innstillinger kan skade innholdet i dine delte mapper og hindre Syncthing i å fungere.",
"Incorrect user name or password.": "Feil brukernavn eller passord.",
"Internally used paths:": "Interne stier:",
"Introduced By": "Introdusert av",
"Introducer": "Introduktør",
"Introduction": "Introduksjon",
@@ -202,6 +223,7 @@
"Last seen": "Sist sett",
"Latest Change": "Sist endret",
"Learn more": "Lær mer",
"Learn more at {%url%}": "Lær mer her {{url}}",
"Limit": "Grense",
"Listeners": "Lyttere",
"Loading data...": "Laster inn data…",

View File

@@ -230,7 +230,7 @@
"Listeners": "Lyssnare",
"Loading data...": "Läser in data...",
"Loading...": "Läser in...",
"Local Additions": "Lokala tillägg",
"Local Additions": "Lokalt tillägg",
"Local Discovery": "Lokal annonsering",
"Local State": "Lokalt tillstånd",
"Local State (Total)": "Lokalt tillstånd (totalt)",
@@ -369,7 +369,7 @@
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Visas istället för enhets-ID i klusterstatus. Kommer att annonseras på andra enheter som ett valfritt standardnamn.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Visas istället för enhets-ID i klusterstatusen. Kommer att uppdateras till det namn som enheten annonserar om det lämnas tomt.",
"Shutdown": "Stäng av",
"Shutdown Complete": "Avstängning klar",
"Shutdown Complete": "Avstängning slutförd",
"Simple": "Enkel",
"Simple File Versioning": "Enkel filversionshantering",
"Single level wildcard (matches within a directory only)": "Jokertecken på en nivå (matchar endast i en mapp)",
@@ -398,7 +398,7 @@
"Sync Status": "Synkroniseringsstatus",
"Syncing": "Synkroniserar",
"Syncthing device ID for \"{%devicename%}\"": "Synkronisera enhets-ID för \"{{devicename}}\"",
"Syncthing has been shut down.": "Syncthing har stängts.",
"Syncthing has been shut down.": "Synkronisering har stängts av.",
"Syncthing includes the following software or portions thereof:": "Syncthing innehåller följande mjukvarupaket eller delar av dem:",
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing har fri och öppen källkod licensierad som MPL v2.0.",
"Syncthing is a continuous file synchronization program. It synchronizes files between two or more computers in real time, safely protected from prying eyes. Your data is your data alone and you deserve to choose where it is stored, whether it is shared with some third party, and how it's transmitted over the internet.": "Syncthing är ett program för kontinuerlig filsynkronisering. Den synkroniserar filer mellan två eller flera datorer i realtid, säkert skyddade från nyfikna ögon. Dina data är enbart din data och du förtjänar att välja var den lagras, om den delas med någon tredje part och hur den överförs över internet.",
@@ -408,7 +408,7 @@
"Syncthing is saving changes.": "Syncthing sparar ändringar.",
"Syncthing is upgrading.": "Syncthing uppgraderas.",
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing stöder nu automatiskt kraschrapportering till utvecklarna. Denna funktion är aktiverad som standard.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing verkar vara avstängt, eller så finns det problem med din internetanslutning. Försöker igen…",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing verkar vara avstängd, eller så finns det problem med din internetanslutning. Försöker igen…",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing verkar ha drabbats av ett problem med behandlingen av din förfrågan. Uppdatera sidan eller starta om Syncthing om problemet kvarstår.",
"TCP LAN": "TCP LAN",
"TCP WAN": "TCP WAN",

View File

@@ -1,186 +1,186 @@
{
"A device with that ID is already added.": "Пристрій з таким ID вже додано.",
"A negative number of days doesn't make sense.": "Від'ємна кількість днів немає сенсу.",
"A new major version may not be compatible with previous versions.": "Нова версія з великими змінвми може бути несумісною із попередніми версіями.",
"A device with that ID is already added.": "Пристрій із таким ID вже додано.",
"A negative number of days doesn't make sense.": "Від'ємна кількість днів не має сенсу.",
"A new major version may not be compatible with previous versions.": "Нова головна версія може бути несумісною із попередніми версіями.",
"API Key": "API ключ",
"About": "Про програму",
"About": "Про застосунок",
"Action": "Дія",
"Actions": "Дії",
"Active filter rules": "Діючі правила фільтрування",
"Active filter rules": "Активні правила фільтрування",
"Add": "Додати",
"Add Device": "Додати пристрій",
"Add Folder": "Додати папку",
"Add Folder": "Додати теку",
"Add Remote Device": "Додати віддалений пристрій",
"Add devices from the introducer to our device list, for mutually shared folders.": "Додавати пристрої з пристрою що рекомендує, до списку пристроїв для налаштування спільних папок.",
"Add filter entry": "Додати правило фільтру",
"Add devices from the introducer to our device list, for mutually shared folders.": "Додати пристрої від уповноваженого до нашого списку пристроїв для взаємно спільних папок.",
"Add filter entry": "Додати запис фільтрування",
"Add ignore patterns": "Додати шаблони ігнорування",
"Add new folder?": "Додати нову папку?",
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Крім того, буде збільшений інтервал повного сканування (у 60 разів, тобто нове значення за замовчанням - 1 година). Ви також можете налаштувати його вручну для кожної папки пізніше після вибору \"Ні\".",
"Add new folder?": "Додати нову теку?",
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Крім того, буде інтервал повного сканування буде збільшено (в 60 разів, тобто нове типове значення - 1 година). Ви також зможете налаштувати його вручну для кожної теки пізніше, вибравши \"Ні\".",
"Address": "Адреса",
"Addresses": "Адреси",
"Advanced": "Розширені",
"Advanced Configuration": "Розширена конфігурація",
"Advanced Configuration": "Розширене налаштування",
"All Data": "Усі дані",
"All Time": "Весь час",
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Ті папки, якими поділилися з цим пристроєм, мають бути захищені паролем, щоб усі надіслані дані неможливо було прочитати без вказаного пароля.",
"Allow Anonymous Usage Reporting?": "Дозволити програмі збирати анонімну статистику використання?",
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Усі спільні теки з цим пристроєм, повинні бути захищені паролем, щоб усі надіслані дані неможливо було прочитати без вказаного пароля.",
"Allow Anonymous Usage Reporting?": "Дозволити анонімне звітування про використання?",
"Allowed Networks": "Дозволені мережі",
"Alphabetic": "За абеткою",
"Altered by ignoring deletes.": "Змінено шляхом ігнорування видалень.",
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Зовнішня команда для керування версіями. Вона має видалити файл зі спільної папки. Якщо шлях до програми містить пробіли, його слід взяти в лапки.",
"Anonymous Usage Reporting": "Анонімізована статистика використання",
"Anonymous usage report format has changed. Would you like to move to the new format?": "Змінився формат анонімного звіту про користування. Бажаєте перейти на новий формат?",
"Altered by ignoring deletes.": "Змінено, ігноруючи видалення.",
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Зовнішня команда керує версіями. Вона повинна видалити файл із спільної теки. Якщо шлях до застосунку містить пробіли, його слід взяти в лапки.",
"Anonymous Usage Reporting": "Анонімне звітування про використання",
"Anonymous usage report format has changed. Would you like to move to the new format?": "Формат анонімного звітування про використання змінився. Бажаєте перейти на новий формат?",
"Applied to LAN": "Застосовано до LAN",
"Apply": "Застосувати",
"Are you sure you want to override all remote changes?": "Ви впевнені, що бажаєте відхилити всі зміни у віддалених папках?",
"Are you sure you want to permanently delete all these files?": "Ви впевнені, що бажаєте остаточно видалити всі ці файли?",
"Are you sure you want to remove device {%name%}?": "Чи ви впевнені в необхідності видалити пристрій {{name}}?",
"Are you sure you want to remove folder {%label%}?": "Ви впевнені, що хочете видалити папку {{label}}?",
"Are you sure you want to restore {%count%} files?": "Чи ви впевнені в необхідності відновити наступну к-сть файлів: {{count}} ?",
"Are you sure you want to revert all local changes?": "Ви впевнені, що бажаєте відкинути всі локальні зміни?",
"Are you sure you want to upgrade?": "Напевно хочете оновити?",
"Authentication Required": "Потрібна авторизація",
"Are you sure you want to override all remote changes?": "Ви впевнені, що хочете перезаписати всі віддалені зміни?",
"Are you sure you want to permanently delete all these files?": "Ви впевнені, що хочете остаточно видалити всі ці файли?",
"Are you sure you want to remove device {%name%}?": "Ви впевнені, що хочете видалити пристрій {{name}}?",
"Are you sure you want to remove folder {%label%}?": "Ви впевнені, що хочете видалити теку {{label}}?",
"Are you sure you want to restore {%count%} files?": "Ви впевнені, що хочете відновити {{count}} файли(-ів)?",
"Are you sure you want to revert all local changes?": "Ви впевнені, що хочете повернути всі локальні зміни?",
"Are you sure you want to upgrade?": "Ви впевнені, що хочете оновити?",
"Authentication Required": "Необхідна автентифікація",
"Authors": "Автори",
"Auto Accept": "Автоприймання",
"Auto Accept": "Автоприйняття",
"Automatic Crash Reporting": "Автоматичне звітування про збої",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Автоматиче оновлення зараз дозволяє обирати між стабільними випусками та реліз-кандидатами.",
"Automatic upgrades": "Автоматичне оновлення",
"Automatic upgrades are always enabled for candidate releases.": "Автоматичні оновлення завжди увімкнені для реліз-кандидатів.",
"Automatically create or share folders that this device advertises at the default path.": "Автоматично створювати або поширювати каталоги, які цей пристрій декларує як створені по замовчанню.",
"Available debug logging facilities:": "Доступні засоби журналу для відладки:",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Автоматичне оновлення тепер пропонує вибір між стабільними випусками та кандидатами на випуск.",
"Automatic upgrades": "Автоматичні оновлення",
"Automatic upgrades are always enabled for candidate releases.": "Автоматичні оновлення завжди ввімкнені для кандидатів на випуск.",
"Automatically create or share folders that this device advertises at the default path.": "Автоматично створювати або ділитися теками, які цей пристрій пропонує типово.",
"Available debug logging facilities:": "Доступні засоби ведення журналу налагодження:",
"Be careful!": "Будьте обережні!",
"Body:": "Повідомлення:",
"Bugs": "Помилки",
"Cancel": "Скасувати",
"Changelog": "Перелік змін",
"Changelog": "Журнал змін",
"Clean out after": "Очистити після",
"Cleaning Versions": "Очищення версій",
"Cleanup Interval": "Інтервал очищення",
"Click to see full identification string and QR code.": "Натисніть, щоб переглянути повний ідентифікаційний рядок та QR-код.",
"Click to see full identification string and QR code.": "Натисніть, щоб переглянути повний ID та QR-код.",
"Close": "Закрити",
"Command": "Команда",
"Comment, when used at the start of a line": "Коментар, якщо використовується на початку рядка",
"Compression": "Стиснення",
"Configuration Directory": "Директорія з конфігураційними файлами",
"Configuration File": "Конфігураційний файл",
"Configuration Directory": "Тека з налаштуваннями",
"Configuration File": "Файл налаштувань",
"Configured": "Налаштовано",
"Connected (Unused)": "Під'єднано (не використовується)",
"Connection Error": "Помилка з’єднання",
"Connection Management": "Керування з'єднанням",
"Connection Error": "Помилка під’єднання",
"Connection Management": "Керування з'єднаннями",
"Connection Type": "Тип з'єднання",
"Connections": "З'єднання",
"Connections via relays might be rate limited by the relay": "Швидкість з’єднання через реле може бути обмежена ним",
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Постійне стеження за змінами наразі доступне у Syncthing. Це дозволить виявити зміни на диску та сканувати тільки модифіковані шляхи. Переваги полягають у тому, що зміни поширюються швидше і зменшується кількість повних пересканувань.",
"Connections via relays might be rate limited by the relay": "З’єднання через реле можуть бути обмежені за швидкістю реле",
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "У Syncthing тепер доступна функція безперервного відстеження змін. Це дозволить виявляти зміни на диску та сканувати лише модифіковані шляхи. Переваги полягають у тому, що зміни поширюються швидше й зменшується кількість повних сканувань.",
"Copied from elsewhere": "Скопійовано з іншого місця",
"Copied from original": "Скопійовано з оригіналу",
"Copied!": "Скопійовано!",
"Copy": "Копіювати",
"Copy failed! Try to select and copy manually.": "Помилка копіювання! Спробуйте вибрати та скопіювати вручну.",
"Currently Shared With Devices": "На даний момент є спільний доступ пристроїв",
"Custom Range": "Вибрати діапазон",
"Danger!": "Небезпека!",
"Database Location": "Місцезнаходження бази даних",
"Debugging Facilities": "Засоби відладки",
"Default": "За замовчанням",
"Default Configuration": "Конфігурація за замовчуванням",
"Default Device": "Пристрій за замовчуванням",
"Default Folder": "Папка за замовчуванням",
"Default Ignore Patterns": "Шаблони ігнорування за замовчуванням",
"Defaults": "Налаштування за замовчуванням",
"Copy failed! Try to select and copy manually.": "Не вдалося скопіювати! Спробуйте виділити та скопіювати вручну.",
"Currently Shared With Devices": "Наразі ділиться із пристроями",
"Custom Range": "Обрати діапазон",
"Danger!": "Небезпечно!",
"Database Location": "Розташування бази даних",
"Debugging Facilities": "Засоби налагодження",
"Default": "Типово",
"Default Configuration": "Типові налаштування",
"Default Device": "Типовий пристрій",
"Default Folder": "Типова тека",
"Default Ignore Patterns": "Типові шаблони ігнорування",
"Defaults": "Типово",
"Delete": "Видалити",
"Delete Unexpected Items": "Видалити неочікувані елементи",
"Deleted {%file%}": "Видалено {{file}}",
"Deleted {%file%}": "{{file}} видалено",
"Deselect All": "Зняти вибір з усіх",
"Deselect devices to stop sharing this folder with.": "Зніміть вибір з пристроїв, щоб припинити їх доступ до цієї папки.",
"Deselect folders to stop sharing with this device.": "Зніміть галочки біля папок, щоб припинити обмін файлами з цим пристроєм.",
"Deselect devices to stop sharing this folder with.": "Зніміть вибір із пристроїв, щоби припинити спільний доступ до цієї теки.",
"Deselect folders to stop sharing with this device.": "Зніміть вибір із тек, щоби припинити спільний доступ із цим пристроєм.",
"Device": "Пристрій",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Пристрій \"{{name}}\" ({{device}} за адресою {{address}}) намагається під’єднатися. Додати новий пристрій?",
"Device Certificate": "Сертифікат пристрою",
"Device ID": "ID пристрою",
"Device Identification": "Ідентифікатор пристрою",
"Device Identification": "Ідентифікація пристрою",
"Device Name": "Назва пристрою",
"Device Status": "Статус пристрою",
"Device Status": "Стан пристрою",
"Device is untrusted, enter encryption password": "Пристрій ненадійний, введіть пароль для шифрування",
"Device rate limits": "Обмеження пристрою",
"Device that last modified the item": "Пристрій, що останнім змінив елемент",
"Device that last modified the item": "Пристрій, який останнім змінив елемент",
"Devices": "Пристрої",
"Disable Crash Reporting": "Вимкнути звітування про збої",
"Disabled": "Вимкнено",
"Disabled periodic scanning and disabled watching for changes": "Відключено періодичне сканування та відключено відстеження змін",
"Disabled periodic scanning and enabled watching for changes": "Відключено періодичне сканування та увімкнене стеження за змінами",
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Відключено періодичне сканування та не вдається налаштувати перегляд змін, повторення кожну 1 хв:",
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Вимикає порівняння та синхронізацію дозволів на файли. Корисно для систем з відсутніми або особливими дозволами (наприклад: FAT, exFAT, Synology, Android).",
"Discard": "Відхили",
"Disconnected": "Зєднання відсутнє",
"Disconnected (Inactive)": "Від'єднаний (неактивний)",
"Disabled periodic scanning and disabled watching for changes": "Вимкнено періодичне сканування та вимкнено відстеження змін",
"Disabled periodic scanning and enabled watching for changes": "Вимкнено періодичне сканування та ввімкнено відстеження змін",
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Вимкнено періодичне сканування та не вдалося налаштувати відстеження змін, повторна спроба кожну 1хв:",
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Вимикає порівняння та синхронізацію дозволів для файлів. Корисно на системах із відсутніми або нестандартними дозволами (наприклад: FAT, exFAT, Synology, Android).",
"Discard": "Відхилити",
"Disconnected": "Від'єднано",
"Disconnected (Inactive)": "Від'єднано (неактивно)",
"Disconnected (Unused)": "Від'єднано (не використовується)",
"Discovered": "Виявлено",
"Discovery": "Сервери координації NAT",
"Discovery": "Виявлення",
"Discovery Failures": "Помилки виявлення",
"Discovery Status": "Стан виявлення",
"Dismiss": "Відхилити",
"Do not add it to the ignore list, so this notification may recur.": "Не додавати його до списку ігнорування, але тоді це сповіщення може повторюватися.",
"Do not add it to the ignore list, so this notification may recur.": "Не додавайте це до списку ігнорування, тому це сповіщення може повторитися.",
"Do not restore": "Не відновлювати",
"Do not restore all": "Не відновлювати все",
"Do you want to enable watching for changes for all your folders?": "Бажаєте увімкнути стеження за змінами у всіх ваших папках?",
"Do you want to enable watching for changes for all your folders?": "Бажаєте ввімкнути відстеження змін для всіх ваших тек?",
"Documentation": "Документація",
"Download Rate": "Швидкість завантаження",
"Downloaded": "Завантажено",
"Downloading": "Завантажується",
"Edit": "Редагуй",
"Edit Device": "Налаштування пристрою",
"Edit Device Defaults": "Редагувати параметри пристрою за замовчуванням",
"Edit Folder": "Налаштування папки",
"Edit Folder Defaults": "Редагувати параметри папки за замовчуванням",
"Downloading": "Завантаження",
"Edit": "Редагувати",
"Edit Device": "Редагувати пристрій",
"Edit Device Defaults": "Редагувати типові налаштування пристрою",
"Edit Folder": "Редагувати теку",
"Edit Folder Defaults": "Редагувати типові налаштування теки",
"Editing {%path%}.": "Редагування {{path}}.",
"Enable Crash Reporting": "Увімкнути звітування про збої",
"Enable NAT traversal": "Увімкнути NAT traversal",
"Enable Relaying": "Увімкнути ретрансляцію (relaying)",
"Enabled": "Увімкнено",
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Дозволяє надсилати інформацію про розширені атрибути на інші пристрої та застосовувати отриману також. Може вимагати запуску з підвищеними привілеями.",
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Дозволяє надсилати інформацію про розширені атрибути на інші пристрої, але не застосовувати отриману. Це може мати значний вплив на продуктивність. Завжди ввімкнено, коли ввімкнено «Синхронізувати розширені атрибути».",
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Дозволяє надсилати інформацію про права власності щодо файлів на інші пристрої, і застосовувати отриману також. Зазвичай вимагає запуску з підвищеними привілеями.",
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Дозволяє надсилати інформацію про права власності щодо файлів на інші пристрої, але не застосовувати отриману. Це може мати значний вплив на продуктивність. Завжди ввімкнено, якщо ввімкнено «Синхронізувати права власності».",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Введіть невід'ємне число (напр. \"2.35\") та виберіть пристрій. Проценти від загального дискового простору.",
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Вмикає надсилання розширених атрибутів іншим пристроям та застосування вхідних. Може вимагати виконання із підвищеними привілеями.",
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Вмикає надсилання розширених атрибутів іншим пристроям, але без застосування вхідних. Це може суттєво вплинути на продуктивність. Завжди ввімкнено, коли ввімкнено «Синхронізувати розширені атрибути».",
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Вмикає надсилання інформації про власність іншим пристроям та застосування вхідної. Зазвичай вимагає виконання із підвищеними привілеями.",
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Вмикає надсилання інформації про власність іншим пристроям, але без застосування вхідної. Це може суттєво вплинути на продуктивність. Завжди ввімкнено, якщо ввімкнено «Синхронізувати права власності».",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Введіть невід'ємне число (напр., \"2.35\") та виберіть одиницю вимірювання. Відсотки вказуються як частина загального розміру диска.",
"Enter a non-privileged port number (1024 - 65535).": "Введіть номер непривілейованого порту (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Введіть адреси, розділені комою (\"tcp://ip:port\", \"tcp://host:port\"), або лише \"dynamic\" для автоматичного визначення адреси.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Введіть адреси, розділені комою (\"tcp://ip:port\", \"tcp://host:port\") або \"dynamic\" для автоматичного виявлення адреси.",
"Enter ignore patterns, one per line.": "Введіть шаблони ігнорування, по одному на рядок.",
"Enter up to three octal digits.": "Введіть до трьох вісімкових цифр.",
"Error": "Помилка",
"Extended Attributes": "Розширені атрибути",
"Extended Attributes Filter": "Фільтр за розширеними атрибутами",
"Extended Attributes Filter": "Фільтр розширених атрибутів",
"External": "Зовнішній",
"External File Versioning": "Зовнішне керування версіями",
"External File Versioning": "Зовнішнє версіонування файлів",
"Failed Items": "Невдалі",
"Failed to load file versions.": "Не вдалося завантажити версії файлів.",
"Failed to load ignore patterns.": "Не вдалося завантажити шаблони ігнорування.",
"Failed to setup, retrying": "Помилка при налаштуванні, повторюємо",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "За відсутності IPv6-з'єднання очікується неможливість підключення до IPv6-серверів.",
"Failed to setup, retrying": "Не вдалося налаштувати, повторна спроба",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "За відсутності з'єднання IPv6 очікується неможливість під'єднання до серверів IPv6.",
"File Pull Order": "Порядок витягнення файлів",
"File Versioning": "Керування версіями",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Файли, що замінюються або видаляються Syncthing, переміщуються у директорію .stversions. ",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Файли будуть поміщатися у директорію .stversions із відповідною позначкою часу, коли вони будуть замінятися або видалятися програмою.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Вміст папки захищено від змін, зроблених на інших пристроях, але зміни зроблені на цьому пристрої можна розіслати решті пристроїв кластеру.",
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Файли синхронізуються з кластера, але будь-які внесені локально зміни не надсилатимуться на інші пристрої.",
"File Versioning": "Версіонування файлів",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Файли переміщуються до теки .stversions, коли вони замінюються або видаляються Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Файли переміщуються до версій із позначкою дати в теку .stversions, коли вони замінюються або видаляються Syncthing.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Файли захищено від змін, внесених на інших пристроях, але зміни зроблені на цьому пристрої, будуть надіслані решті пристроїв кластеру.",
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Файли синхронізовано з кластеру, але будь-які внесені локально зміни не будуть надіслані на інші пристрої.",
"Filesystem Watcher Errors": "Помилки спостерігача файлової системи",
"Filter by date": "Фільтрувати по даті",
"Filter by name": "Фільтрувати по імені",
"Folder": "Папка",
"Folder ID": "ID папки",
"Folder Label": "Назва папки",
"Folder Path": "Шлях до папки",
"Folder Status": "Статус папки",
"Folder Type": "Тип папки",
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Тип папки \"{{receiveEncrypted}}\" можна встановити лише під час додавання нової папки.",
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Тип папки \"{{receiveEncrypted}}\" не можна змінити після її додавання. Потрібно видалити її спочатку, далі видалити або розшифрувати дані на диску, а потім додати папку знову.",
"Folders": "Папки",
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Сталася помилка при спробі відслідковувати зміни у вищенаведених папках. Їх доступність перевірятиметься щохвилини, доки помилка не зникне. Якщо помилки не зникають, спробуйте виправити права доступу або попросіть допомоги.",
"Filter by date": "Фільтрувати за датою",
"Filter by name": "Фільтрувати за назвою",
"Folder": "Тека",
"Folder ID": "ID теки",
"Folder Label": "Назва теки",
"Folder Path": "Шлях до теки",
"Folder Status": "Стан теки",
"Folder Type": "Тип теки",
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Тип теки \"{{receiveEncrypted}}\" можна встановити лише під час додавання нової теки.",
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Тип теки \"{{receiveEncrypted}}\" не можна змінити після її додавання. Вам потрібно видалити теку, розшифрувати чи видалити дані на диску, а потім додати теку знову.",
"Folders": "Теки",
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Для наступних тек сталася помилка під час початку відстеження змін. Перевірка тек відбувається щохвилини, тому помилки можуть незабаром зникнути. Якщо помилки залишилися, спробуйте виправити основну проблему та зверніться за допомогою, якщо не зможете.",
"Forever": "Назавжди",
"Full Rescan Interval (s)": "Інтервал повного пересканування (секунди)",
"GUI": "Панель керування",
"GUI / API HTTPS Certificate": "HTTPS-сертифікати панелі керування / API",
"GUI Authentication Password": "Пароль для доступу до панелі керування",
"GUI Authentication User": "Логін користувача для доступу до панелі керування",
"Full Rescan Interval (s)": "Інтервал повного пересканування (у секундах)",
"GUI": "Графічний інтерфейс",
"GUI / API HTTPS Certificate": "HTTPS сертифікат для GUI / API",
"GUI Authentication Password": "Пароль аутентифікації у графічному інтерфейсі",
"GUI Authentication User": "Користувач аутентифікації у графічному інтерфейсі",
"GUI Authentication: Set User and Password": "Доступ до панелі керування: встановіть ім'я користувача та пароль",
"GUI Listen Address": "Адреса прослуховування для панелі керування",
"GUI Override Directory": "Перевизначення адреси панелі керування",
@@ -200,13 +200,13 @@
"Ignore": "Ігнорувати",
"Ignore Patterns": "Шаблони винятків",
"Ignore Permissions": "Ігнорувати права доступу до файлів",
"Ignore patterns can only be added after the folder is created. If checked, an input field to enter ignore patterns will be presented after saving.": "Шаблони ігнорування можна додати лише після створення папки. Якщо галочку поставлено, після збереження відображатиметься поле для введення шаблонів.",
"Ignore patterns can only be added after the folder is created. If checked, an input field to enter ignore patterns will be presented after saving.": "Шаблони ігнорування можна додати лише після створення теки. Якщо галочку поставлено, після збереження відображатиметься поле для введення шаблонів.",
"Ignored Devices": "Ігноровані пристрої",
"Ignored Folders": "Ігноровані папки",
"Ignored Folders": "Ігноровані теки",
"Ignored at": "Ігноруються в",
"Included Software": "Включене ПЗ",
"Incoming Rate Limit (KiB/s)": "Ліміт швидкості завантаження (КіБ/с)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Невірна конфігурація може пошкодити вміст вашої папки та зробити Syncthing недієздатним.",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Невірна конфігурація може пошкодити вміст вашої теки та зробити Syncthing недієздатним.",
"Incorrect user name or password.": "Невірний логін або пароль.",
"Internally used paths:": "Шляхи, що використовуються внутрішньо:",
"Introduced By": "Рекомендовано",
@@ -260,7 +260,7 @@
"Multi level wildcard (matches multiple directory levels)": "Багаторівнева маска (пошук збігів в усіх піддиректоріях) ",
"Never": "Ніколи",
"New Device": "Новий пристрій",
"New Folder": "Нова папка",
"New Folder": "Нова тека",
"Newest First": "Спершу новіші",
"No": "Ні",
"No File Versioning": "Версіювання вимкнено",

View File

@@ -118,10 +118,6 @@
<li ng-if="authenticated"><a href="" ng-click="showSettings()"><span class="fa fa-fw fa-cog"></span>&nbsp;<span translate>Settings</span></a></li>
<li ng-if="authenticated"><a href="" ng-click="showDeviceIdentification(thisDevice())"><span class="fa fa-fw fa-qrcode"></span>&nbsp;<span translate>Show ID</span></a></li>
<li ng-if="authenticated" class="divider" aria-hidden="true"></li>
<li ng-if="authenticated"><a href="" ng-click="shutdown()"><span class="fa fa-fw fa-power-off"></span>&nbsp;<span translate>Shutdown</span></a></li>
<li ng-if="authenticated"><a href="" ng-click="restart()"><span class="fa fa-fw fa-refresh"></span>&nbsp;<span translate>Restart</span></a></li>
<li ng-if="authenticated" class="divider" aria-hidden="true"></li>
<li ng-if="authenticated"><a href="" ng-click="advanced()"><span class="fa fa-fw fa-cogs"></span>&nbsp;<span translate>Advanced</span></a></li>
<li ng-if="authenticated"><a href="" ng-click="logging.show()"><span class="fa fa-fw fa-wrench"></span>&nbsp;<span translate>Logs</span></a></li>
@@ -129,8 +125,10 @@
<li class="divider" aria-hidden="true" ng-if="config.gui.debugging"></li>
<li><a href="/rest/debug/support" target="_blank" ng-if="config.gui.debugging"><span class="fa fa-fw fa-user-md"></span>&nbsp;<span translate>Support Bundle</span></a></li>
<li ng-if="authenticated && isAuthEnabled()" class="divider" aria-hidden="true"></li>
<li ng-if="authenticated" class="divider" aria-hidden="true"></li>
<li ng-if="authenticated && isAuthEnabled()"><a href="" ng-click="logout()"><span class="far fa-fw fa-sign-out"></span>&nbsp;<span translate>Log Out</span></a></li>
<li ng-if="authenticated"><a href="" ng-click="restart()"><span class="fa fa-fw fa-refresh"></span>&nbsp;<span translate>Restart</span></a></li>
<li ng-if="authenticated"><a href="" ng-click="shutdown()"><span class="fa fa-fw fa-power-off"></span>&nbsp;<span translate>Shutdown</span></a></li>
</ul>
</li>
</ul>

View File

@@ -30,7 +30,7 @@
<h4 class="text-center" translate>The Syncthing Authors</h4>
<div class="row">
<div class="col-md-12" id="contributor-list">
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Emil Lundberg, Eric P, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, bt90, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Anatoli Babenia, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, DerRockWolf, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, Gusted, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, K.B.Dharun Krishna, Kalle Laine, Karol Różycki, Kebin Liu, Keith Harrison, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Luke Hamburg, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Martin Polehla, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, Maximilian, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Ryan Qian, Sacheendra Talluri, Scott Klupfel, Sertonix, Severin von Wnuck-Lipinski, Shaarad Dalvi, Simon Mwepu, Simon Pickup, Sly_tom_cat, Sonu Kumar Saw, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Taylor Khan, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tim Nordenfur, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tommy van der Vorst, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, Vladimir Rusinov, WangXi, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, cjc7373, cui fliter, d-volution, derekriemer, desbma, diemade, digital, entity0xfe, georgespatton, ghjklw, guangwu, gudvinr, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, kylosus, luchenhan, luzpaz, marco-m, maxice8, mclang, mv1005, nf, orangekame3, otbutz, overkill, perewa, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Emil Lundberg, Eric P, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, bt90, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Ionescu, Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Anatoli Babenia, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, DerRockWolf, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, Gusted, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hireworks, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, K.B.Dharun Krishna, Kalle Laine, Kapil Sareen, Karol Różycki, Kebin Liu, Keith Harrison, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Luke Hamburg, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Martin Polehla, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, Maximilian, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Ryan Qian, Sacheendra Talluri, Scott Klupfel, Sertonix, Severin von Wnuck-Lipinski, Shaarad Dalvi, Simon Mwepu, Simon Pickup, Sly_tom_cat, Sonu Kumar Saw, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Taylor Khan, Terrance, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tim Nordenfur, Tobias Frölich, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tommy van der Vorst, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, Vladimir Rusinov, WangXi, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, cjc7373, cui fliter, d-volution, derekriemer, desbma, diemade, digital, entity0xfe, georgespatton, ghjklw, guangwu, gudvinr, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, kylosus, luchenhan, luzpaz, marco-m, maxice8, mclang, mv1005, nf, orangekame3, otbutz, overkill, perewa, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
</div>
</div>
</div>
@@ -55,7 +55,6 @@ Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Al
<li><a href="https://github.com/chmduquesne/rollinghash">chmduquesne/rollinghash</a>, Copyright &copy; 2015 Christophe-Marie Duquesne.</li>
<li><a href="https://github.com/d4l3k/messagediff">d4l3k/messagediff</a>, Copyright &copy; 2015 Tristan Rice.</li>
<li><a href="https://github.com/gobwas/glob">gobwas/glob</a>, Copyright &copy; 2016 Sergey Kamardin.</li>
<li><a href="https://github.com/gogo/protobuf">gogo/protobuf</a>, Copyright &copy; 2013 The GoGo Authors.</li>
<li><a href="https://github.com/golang/groupcache">golang/groupcache</a>, Copyright &copy; 2013 Google Inc.</li>
<li><a href="https://github.com/golang/protobuf">golang/protobuf</a>, Copyright &copy; 2010 The Go Authors.</li>
<li><a href="https://github.com/golang/snappy">golang/snappy</a>, Copyright &copy; 2011 The Snappy-Go Authors.</li>

View File

@@ -36,7 +36,7 @@
</span>
<span ng-switch="selected[id] && folderType !== 'receiveencrypted'" class="input-group-addon">
<span ng-switch-when='true'>
<span class="button fas fa-fw fa-eye" ng-click="togglePasswordVisibility()"></span>
<span class="button fas fa-fw {{plain ? 'fa-eye-slash' : 'fa-eye'}}" ng-click="togglePasswordVisibility()"></span>
</span>
<span ng-switch-default>
<span class="button fas fa-fw fa-eye" disabled></span>

View File

@@ -6,7 +6,12 @@ angular.module('syncthing.core')
ctrl.$validators.folderPathErrors = function (viewValue) {
// This function checks whether ydir is a subdirectory of xdir,
// e.g. it would return true if xdir = "/home/a", ydir = "/home/a/b".
// Tildes in both xdir and ydir are expanded for comparison
// so that e.g. xdir = "home/a/", ydir = "~/b" will return true.
function isSubDir(xdir, ydir) {
var tildeExpansionRegex = new RegExp(`^~${scope.system.pathSeparator}|^~/`);
xdir = xdir.replace(tildeExpansionRegex, `${scope.system.tilde}${scope.system.pathSeparator}`);
ydir = ydir.replace(tildeExpansionRegex, `${scope.system.tilde}${scope.system.pathSeparator}`);
var xdirArr = xdir.split(scope.system.pathSeparator);
var ydirArr = ydir.split(scope.system.pathSeparator);
if (xdirArr.slice(-1).pop() === "") {

View File

@@ -3343,6 +3343,11 @@ angular.module('syncthing.core')
return 'checkbox';
}
if (value instanceof Array) {
if (value.some(function (element) {
return typeof element !== 'number' && typeof element !== 'string';
})) {
return 'skip';
}
return 'list';
}
if (typeof value === 'object') {
@@ -3698,7 +3703,6 @@ angular.module('syncthing.core')
untrusted: '=',
},
link: function (scope, elem, attrs) {
var plain = false;
scope.togglePasswordVisibility = function() {
scope.plain = !scope.plain;
};

View File

@@ -1,6 +1,6 @@
<modal id="idqr" status="info" icon="fas fa-qrcode" heading="{{'Device Identification' | translate}} - {{deviceName(currentDevice)}}" large="yes" closeable="yes">
<div class="modal-body text-center">
<div class="well well-sm text-monospace select-on-click">{{currentDevice.deviceID}}</div>
<div class="well well-sm text-monospace select-on-click"><strong>{{currentDevice.deviceID}}</strong></div>
<div ng-if="currentDevice.deviceID">
<img class="img-thumbnail" ng-src="qr/?text={{currentDevice.deviceID}}" height="328" width="328" alt="{{'QR code' | translate}}" />
<div class="btn-group-vertical" style="vertical-align: top;">

View File

@@ -18,8 +18,8 @@
<div ng-repeat="(key, value) in advancedConfig.gui" ng-init="type = inputTypeFor(key, value)" ng-if="type != 'skip'" class="form-group">
<label for="guiInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}&nbsp;<a href="{{docsURL('users/config#config-option-gui.')}}{{key | lowercase}}" target="_blank"><span class="fas fa-question-circle"></span></a></label>
<div class="col-sm-8">
<input ng-if="inputTypeFor(key, value) == 'list'" id="guiInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.gui[key]" ng-list />
<input ng-if="inputTypeFor(key, value) != 'list'" id="guiInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.gui[key]" />
<input ng-if="type == 'list'" id="guiInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.gui[key]" ng-list />
<input ng-if="type != 'list'" id="guiInput{{$index}}" class="form-control" type="{{type}}" ng-model="advancedConfig.gui[key]" />
</div>
</div>
</form>
@@ -34,11 +34,11 @@
<div id="optionsConfig" class="panel-collapse collapse" role="tabpanel" aria-labelledby="optionsHeading">
<div class="panel-body less-padding">
<form class="form-horizontal" role="form">
<div ng-repeat="(key, value) in advancedConfig.options" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<div ng-repeat="(key, value) in advancedConfig.options" ng-init="type = inputTypeFor(key, value)" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<label for="optionsInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}&nbsp;<a href="{{docsURL('users/config#config-option-options.')}}{{key | lowercase}}" target="_blank"><span class="fas fa-question-circle"></span></a></label>
<div class="col-sm-8">
<input ng-if="inputTypeFor(key, value) == 'list'" id="optionsInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.options[key]" ng-list />
<input ng-if="inputTypeFor(key, value) != 'list'" id="optionsInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.options[key]" />
<input ng-if="type == 'list'" id="optionsInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.options[key]" ng-list />
<input ng-if="type != 'list'" id="optionsInput{{$index}}" class="form-control" type="{{type}}" ng-model="advancedConfig.options[key]" />
</div>
</div>
</form>
@@ -53,11 +53,11 @@
<div id="ldapConfig" class="panel-collapse collapse" role="tabpanel" aria-labelledby="ldapHeading">
<div class="panel-body less-padding">
<form class="form-horizontal" role="form">
<div ng-repeat="(key, value) in advancedConfig.ldap" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<div ng-repeat="(key, value) in advancedConfig.ldap" ng-init="type = inputTypeFor(key, value)" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<label for="ldapInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}&nbsp;<a href="{{docsURL('users/config#config-option-ldap.')}}{{key | lowercase}}" target="_blank"><span class="fas fa-question-circle"></span></a></label>
<div class="col-sm-8">
<input ng-if="inputTypeFor(key, value) == 'list'" id="ldapInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.ldap[key]" ng-list />
<input ng-if="inputTypeFor(key, value) != 'list'" id="ldapInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.ldap[key]" />
<input ng-if="type == 'list'" id="ldapInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.ldap[key]" ng-list />
<input ng-if="type != 'list'" id="ldapInput{{$index}}" class="form-control" type="{{type}}" ng-model="advancedConfig.ldap[key]" />
</div>
</div>
</form>
@@ -83,11 +83,11 @@
<div id="folder{{folderIndex}}Config" class="panel-collapse collapse" role="tabpanel" aria-labelledby="folder{{folderIndex}}Heading">
<div class="panel-body less-padding">
<form class="form-horizontal" role="form">
<div ng-repeat="(key, value) in folder" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<div ng-repeat="(key, value) in folder" ng-init="type = inputTypeFor(key, value)" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<label for="folder{{folderIndex}}Input{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}&nbsp;<a href="{{docsURL('users/config#config-option-folder.')}}{{key | lowercase}}" target="_blank"><span class="fas fa-question-circle"></span></a></label>
<div class="col-sm-8">
<input ng-if="inputTypeFor(key, value) == 'list'" id="folder{{folderIndex}}Input{{$index}}" class="form-control" type="text" ng-model="folder[key]" ng-list />
<input ng-if="inputTypeFor(key, value) != 'list'" id="folder{{folderIndex}}Input{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="folder[key]" />
<input ng-if="type == 'list'" id="folder{{folderIndex}}Input{{$index}}" class="form-control" type="text" ng-model="folder[key]" ng-list />
<input ng-if="type != 'list'" id="folder{{folderIndex}}Input{{$index}}" class="form-control" type="{{type}}" ng-model="folder[key]" />
</div>
</div>
</form>
@@ -113,11 +113,11 @@
<div id="device{{deviceIndex}}Config" class="panel-collapse collapse" role="tabpanel" aria-labelledby="device{{deviceIndex}}Heading">
<div class="panel-body less-padding">
<form class="form-horizontal" role="form">
<div ng-repeat="(key, value) in device" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<div ng-repeat="(key, value) in device" ng-init="type = inputTypeFor(key, value)" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<label for="device{{deviceIndex}}Input{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}&nbsp;<a href="{{docsURL('users/config#config-option-device.')}}{{key | lowercase}}" target="_blank"><span class="fas fa-question-circle"></span></a></label>
<div class="col-sm-8">
<input ng-if="inputTypeFor(key, value) == 'list'" id="device{{deviceIndex}}Input{{$index}}" class="form-control" type="text" ng-model="device[key]" ng-list />
<input ng-if="inputTypeFor(key, value) != 'list'" id="device{{deviceIndex}}Input{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="device[key]" />
<input ng-if="type == 'list'" id="device{{deviceIndex}}Input{{$index}}" class="form-control" type="text" ng-model="device[key]" ng-list />
<input ng-if="type != 'list'" id="device{{deviceIndex}}Input{{$index}}" class="form-control" type="{{type}}" ng-model="device[key]" />
</div>
</div>
</form>
@@ -141,11 +141,11 @@
</div>
<div id="advancedDefaultFolder" class="panel-collapse collapse" role="tabpanel" aria-labelledby="advancedDefaultFolderHeading">
<form class="form-horizontal" role="form">
<div ng-repeat="(key, value) in advancedConfig.defaults.folder" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<div ng-repeat="(key, value) in advancedConfig.defaults.folder" ng-init="type = inputTypeFor(key, value)" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<label for="advancedDefaultFolderInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}&nbsp;<a href="{{docsURL('users/config#config-option-folder.')}}{{key | lowercase}}" target="_blank"><span class="fas fa-question-circle"></span></a></label>
<div class="col-sm-8">
<input ng-if="inputTypeFor(key, value) == 'list'" id="advancedDefaultFolderInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.defaults.folder[key]" ng-list />
<input ng-if="inputTypeFor(key, value) != 'list'" id="advancedDefaultFolderInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.defaults.folder[key]" />
<input ng-if="type == 'list'" id="advancedDefaultFolderInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.defaults.folder[key]" ng-list />
<input ng-if="type != 'list'" id="advancedDefaultFolderInput{{$index}}" class="form-control" type="{{type}}" ng-model="advancedConfig.defaults.folder[key]" />
</div>
</div>
</form>
@@ -157,11 +157,11 @@
</div>
<div id="advancedDefaultDevice" class="panel-collapse collapse" role="tabpanel" aria-labelledby="advancedDefaultDeviceHeading">
<form class="form-horizontal" role="form">
<div ng-repeat="(key, value) in advancedConfig.defaults.device" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<div ng-repeat="(key, value) in advancedConfig.defaults.device" ng-init="type = inputTypeFor(key, value)" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<label for="advancedDefaultDeviceInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}&nbsp;<a href="{{docsURL('users/config#config-option-device.')}}{{key | lowercase}}" target="_blank"><span class="fas fa-question-circle"></span></a></label>
<div class="col-sm-8">
<input ng-if="inputTypeFor(key, value) == 'list'" id="advancedDefaultDeviceInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.defaults.device[key]" ng-list />
<input ng-if="inputTypeFor(key, value) != 'list'" id="advancedDefaultDeviceInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.defaults.device[key]" />
<input ng-if="type == 'list'" id="advancedDefaultDeviceInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.defaults.device[key]" ng-list />
<input ng-if="type != 'list'" id="advancedDefaultDeviceInput{{$index}}" class="form-control" type="{{type}}" ng-model="advancedConfig.defaults.device[key]" />
</div>
</div>
</form>
@@ -173,14 +173,14 @@
</div>
<div id="advancedDefaultIgnores" class="panel-collapse collapse" role="tabpanel" aria-labelledby="advancedDefaultIgnoresHeading">
<form class="form-horizontal" role="form">
<div ng-repeat="(key, value) in advancedConfig.defaults.ignores" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<div ng-repeat="(key, value) in advancedConfig.defaults.ignores" ng-init="type = inputTypeFor(key, value)" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
<label for="advancedDefaultIgnoresInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}&nbsp;<a href="{{docsURL('users/config#config-option-defaults.ignores.')}}{{key | lowercase}}" target="_blank"><span class="fas fa-question-circle"></span></a></label>
<div class="col-sm-8">
<div ng-switch="key">
<!-- Special case to preserve empty lines in multi-line input -->
<textarea ng-switch-when="lines" id="advancedDefaultIgnoresInput{{$index}}" class="form-control" rows="5" ng-model="advancedConfig.defaults.ignores._lines" ng-model-options="{ getterSetter: true }"></textarea>
<input ng-switch-default ng-if="inputTypeFor(key, value) == 'list'" id="advancedDefaultIgnoresInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.defaults.ignores[key]" ng-list />
<input ng-switch-default ng-if="inputTypeFor(key, value) != 'list'" id="advancedDefaultIgnoresInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.defaults.ignores[key]" />
<input ng-switch-default ng-if="type == 'list'" id="advancedDefaultIgnoresInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.defaults.ignores[key]" ng-list />
<input ng-switch-default ng-if="type != 'list'" id="advancedDefaultIgnoresInput{{$index}}" class="form-control" type="{{type}}" ng-model="advancedConfig.defaults.ignores[key]" />
</div>
</div>
</div>

View File

@@ -0,0 +1,143 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.1
// protoc (unknown)
// source: apiproto/tokenset.proto
package apiproto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type TokenSet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// token -> expiry time (epoch nanoseconds)
Tokens map[string]int64 `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
}
func (x *TokenSet) Reset() {
*x = TokenSet{}
mi := &file_apiproto_tokenset_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TokenSet) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TokenSet) ProtoMessage() {}
func (x *TokenSet) ProtoReflect() protoreflect.Message {
mi := &file_apiproto_tokenset_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TokenSet.ProtoReflect.Descriptor instead.
func (*TokenSet) Descriptor() ([]byte, []int) {
return file_apiproto_tokenset_proto_rawDescGZIP(), []int{0}
}
func (x *TokenSet) GetTokens() map[string]int64 {
if x != nil {
return x.Tokens
}
return nil
}
var File_apiproto_tokenset_proto protoreflect.FileDescriptor
var file_apiproto_tokenset_proto_rawDesc = []byte{
0x0a, 0x17, 0x61, 0x70, 0x69, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
0x73, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x61, 0x70, 0x69, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0x7d, 0x0a, 0x08, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x74, 0x12,
0x36, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1e, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
0x53, 0x65, 0x74, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x42, 0x93, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x42, 0x0d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x65, 0x74, 0x50, 0x72, 0x6f,
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74,
0x68, 0x69, 0x6e, 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65,
0x6e, 0x2f, 0x61, 0x70, 0x69, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58,
0xaa, 0x02, 0x08, 0x41, 0x70, 0x69, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xca, 0x02, 0x08, 0x41, 0x70,
0x69, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xe2, 0x02, 0x14, 0x41, 0x70, 0x69, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08,
0x41, 0x70, 0x69, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_apiproto_tokenset_proto_rawDescOnce sync.Once
file_apiproto_tokenset_proto_rawDescData = file_apiproto_tokenset_proto_rawDesc
)
func file_apiproto_tokenset_proto_rawDescGZIP() []byte {
file_apiproto_tokenset_proto_rawDescOnce.Do(func() {
file_apiproto_tokenset_proto_rawDescData = protoimpl.X.CompressGZIP(file_apiproto_tokenset_proto_rawDescData)
})
return file_apiproto_tokenset_proto_rawDescData
}
var file_apiproto_tokenset_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_apiproto_tokenset_proto_goTypes = []any{
(*TokenSet)(nil), // 0: apiproto.TokenSet
nil, // 1: apiproto.TokenSet.TokensEntry
}
var file_apiproto_tokenset_proto_depIdxs = []int32{
1, // 0: apiproto.TokenSet.tokens:type_name -> apiproto.TokenSet.TokensEntry
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_apiproto_tokenset_proto_init() }
func file_apiproto_tokenset_proto_init() {
if File_apiproto_tokenset_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_apiproto_tokenset_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_apiproto_tokenset_proto_goTypes,
DependencyIndexes: file_apiproto_tokenset_proto_depIdxs,
MessageInfos: file_apiproto_tokenset_proto_msgTypes,
}.Build()
File_apiproto_tokenset_proto = out.File
file_apiproto_tokenset_proto_rawDesc = nil
file_apiproto_tokenset_proto_goTypes = nil
file_apiproto_tokenset_proto_depIdxs = nil
}

2335
internal/gen/bep/bep.pb.go Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,938 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.1
// protoc (unknown)
// source: dbproto/structs.proto
package dbproto
import (
bep "github.com/syncthing/syncthing/internal/gen/bep"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Same as bep.FileInfo, but without blocks
type FileInfoTruncated struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
ModifiedS int64 `protobuf:"varint,5,opt,name=modified_s,json=modifiedS,proto3" json:"modified_s,omitempty"`
ModifiedBy uint64 `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3" json:"modified_by,omitempty"`
Version *bep.Vector `protobuf:"bytes,9,opt,name=version,proto3" json:"version,omitempty"`
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
SymlinkTarget []byte `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocks_hash,omitempty"`
Encrypted []byte `protobuf:"bytes,19,opt,name=encrypted,proto3" json:"encrypted,omitempty"`
Type bep.FileInfoType `protobuf:"varint,2,opt,name=type,proto3,enum=bep.FileInfoType" json:"type,omitempty"`
Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions,omitempty"`
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
BlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
Platform *bep.PlatformData `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform,omitempty"`
// The local_flags fields stores flags that are relevant to the local
// host only. It is not part of the protocol, doesn't get sent or
// received (we make sure to zero it), nonetheless we need it on our
// struct and to be able to serialize it to/from the database.
LocalFlags uint32 `protobuf:"varint,1000,opt,name=local_flags,json=localFlags,proto3" json:"local_flags,omitempty"`
// The version_hash is an implementation detail and not part of the wire
// format.
VersionHash []byte `protobuf:"bytes,1001,opt,name=version_hash,json=versionHash,proto3" json:"version_hash,omitempty"`
// The time when the inode was last changed (i.e., permissions, xattrs
// etc changed). This is host-local, not sent over the wire.
InodeChangeNs int64 `protobuf:"varint,1002,opt,name=inode_change_ns,json=inodeChangeNs,proto3" json:"inode_change_ns,omitempty"`
// The size of the data appended to the encrypted file on disk. This is
// host-local, not sent over the wire.
EncryptionTrailerSize int32 `protobuf:"varint,1003,opt,name=encryption_trailer_size,json=encryptionTrailerSize,proto3" json:"encryption_trailer_size,omitempty"`
Deleted bool `protobuf:"varint,6,opt,name=deleted,proto3" json:"deleted,omitempty"`
Invalid bool `protobuf:"varint,7,opt,name=invalid,proto3" json:"invalid,omitempty"`
NoPermissions bool `protobuf:"varint,8,opt,name=no_permissions,json=noPermissions,proto3" json:"no_permissions,omitempty"`
}
func (x *FileInfoTruncated) Reset() {
*x = FileInfoTruncated{}
mi := &file_dbproto_structs_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *FileInfoTruncated) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*FileInfoTruncated) ProtoMessage() {}
func (x *FileInfoTruncated) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use FileInfoTruncated.ProtoReflect.Descriptor instead.
func (*FileInfoTruncated) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{0}
}
func (x *FileInfoTruncated) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *FileInfoTruncated) GetSize() int64 {
if x != nil {
return x.Size
}
return 0
}
func (x *FileInfoTruncated) GetModifiedS() int64 {
if x != nil {
return x.ModifiedS
}
return 0
}
func (x *FileInfoTruncated) GetModifiedBy() uint64 {
if x != nil {
return x.ModifiedBy
}
return 0
}
func (x *FileInfoTruncated) GetVersion() *bep.Vector {
if x != nil {
return x.Version
}
return nil
}
func (x *FileInfoTruncated) GetSequence() int64 {
if x != nil {
return x.Sequence
}
return 0
}
func (x *FileInfoTruncated) GetSymlinkTarget() []byte {
if x != nil {
return x.SymlinkTarget
}
return nil
}
func (x *FileInfoTruncated) GetBlocksHash() []byte {
if x != nil {
return x.BlocksHash
}
return nil
}
func (x *FileInfoTruncated) GetEncrypted() []byte {
if x != nil {
return x.Encrypted
}
return nil
}
func (x *FileInfoTruncated) GetType() bep.FileInfoType {
if x != nil {
return x.Type
}
return bep.FileInfoType(0)
}
func (x *FileInfoTruncated) GetPermissions() uint32 {
if x != nil {
return x.Permissions
}
return 0
}
func (x *FileInfoTruncated) GetModifiedNs() int32 {
if x != nil {
return x.ModifiedNs
}
return 0
}
func (x *FileInfoTruncated) GetBlockSize() int32 {
if x != nil {
return x.BlockSize
}
return 0
}
func (x *FileInfoTruncated) GetPlatform() *bep.PlatformData {
if x != nil {
return x.Platform
}
return nil
}
func (x *FileInfoTruncated) GetLocalFlags() uint32 {
if x != nil {
return x.LocalFlags
}
return 0
}
func (x *FileInfoTruncated) GetVersionHash() []byte {
if x != nil {
return x.VersionHash
}
return nil
}
func (x *FileInfoTruncated) GetInodeChangeNs() int64 {
if x != nil {
return x.InodeChangeNs
}
return 0
}
func (x *FileInfoTruncated) GetEncryptionTrailerSize() int32 {
if x != nil {
return x.EncryptionTrailerSize
}
return 0
}
func (x *FileInfoTruncated) GetDeleted() bool {
if x != nil {
return x.Deleted
}
return false
}
func (x *FileInfoTruncated) GetInvalid() bool {
if x != nil {
return x.Invalid
}
return false
}
func (x *FileInfoTruncated) GetNoPermissions() bool {
if x != nil {
return x.NoPermissions
}
return false
}
type FileVersion struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Version *bep.Vector `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
Deleted bool `protobuf:"varint,2,opt,name=deleted,proto3" json:"deleted,omitempty"`
Devices [][]byte `protobuf:"bytes,3,rep,name=devices,proto3" json:"devices,omitempty"`
InvalidDevices [][]byte `protobuf:"bytes,4,rep,name=invalid_devices,json=invalidDevices,proto3" json:"invalid_devices,omitempty"`
}
func (x *FileVersion) Reset() {
*x = FileVersion{}
mi := &file_dbproto_structs_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *FileVersion) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*FileVersion) ProtoMessage() {}
func (x *FileVersion) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use FileVersion.ProtoReflect.Descriptor instead.
func (*FileVersion) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{1}
}
func (x *FileVersion) GetVersion() *bep.Vector {
if x != nil {
return x.Version
}
return nil
}
func (x *FileVersion) GetDeleted() bool {
if x != nil {
return x.Deleted
}
return false
}
func (x *FileVersion) GetDevices() [][]byte {
if x != nil {
return x.Devices
}
return nil
}
func (x *FileVersion) GetInvalidDevices() [][]byte {
if x != nil {
return x.InvalidDevices
}
return nil
}
type VersionList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Versions []*FileVersion `protobuf:"bytes,1,rep,name=versions,proto3" json:"versions,omitempty"`
}
func (x *VersionList) Reset() {
*x = VersionList{}
mi := &file_dbproto_structs_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *VersionList) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*VersionList) ProtoMessage() {}
func (x *VersionList) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use VersionList.ProtoReflect.Descriptor instead.
func (*VersionList) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{2}
}
func (x *VersionList) GetVersions() []*FileVersion {
if x != nil {
return x.Versions
}
return nil
}
// BlockList is the structure used to store block lists
type BlockList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Blocks []*bep.BlockInfo `protobuf:"bytes,1,rep,name=blocks,proto3" json:"blocks,omitempty"`
}
func (x *BlockList) Reset() {
*x = BlockList{}
mi := &file_dbproto_structs_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *BlockList) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BlockList) ProtoMessage() {}
func (x *BlockList) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use BlockList.ProtoReflect.Descriptor instead.
func (*BlockList) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{3}
}
func (x *BlockList) GetBlocks() []*bep.BlockInfo {
if x != nil {
return x.Blocks
}
return nil
}
// IndirectionHashesOnly is used to only unmarshal the indirection hashes
// from a FileInfo
type IndirectionHashesOnly struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocks_hash,omitempty"`
VersionHash []byte `protobuf:"bytes,1001,opt,name=version_hash,json=versionHash,proto3" json:"version_hash,omitempty"`
}
func (x *IndirectionHashesOnly) Reset() {
*x = IndirectionHashesOnly{}
mi := &file_dbproto_structs_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *IndirectionHashesOnly) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*IndirectionHashesOnly) ProtoMessage() {}
func (x *IndirectionHashesOnly) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use IndirectionHashesOnly.ProtoReflect.Descriptor instead.
func (*IndirectionHashesOnly) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{4}
}
func (x *IndirectionHashesOnly) GetBlocksHash() []byte {
if x != nil {
return x.BlocksHash
}
return nil
}
func (x *IndirectionHashesOnly) GetVersionHash() []byte {
if x != nil {
return x.VersionHash
}
return nil
}
// For each folder and device we keep one of these to track the current
// counts and sequence. We also keep one for the global state of the folder.
type Counts struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Files int32 `protobuf:"varint,1,opt,name=files,proto3" json:"files,omitempty"`
Directories int32 `protobuf:"varint,2,opt,name=directories,proto3" json:"directories,omitempty"`
Symlinks int32 `protobuf:"varint,3,opt,name=symlinks,proto3" json:"symlinks,omitempty"`
Deleted int32 `protobuf:"varint,4,opt,name=deleted,proto3" json:"deleted,omitempty"`
Bytes int64 `protobuf:"varint,5,opt,name=bytes,proto3" json:"bytes,omitempty"`
Sequence int64 `protobuf:"varint,6,opt,name=sequence,proto3" json:"sequence,omitempty"` // zero for the global state
DeviceId []byte `protobuf:"bytes,17,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` // device ID for remote devices, or special values for local/global
LocalFlags uint32 `protobuf:"varint,18,opt,name=local_flags,json=localFlags,proto3" json:"local_flags,omitempty"` // the local flag for this count bucket
}
func (x *Counts) Reset() {
*x = Counts{}
mi := &file_dbproto_structs_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Counts) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Counts) ProtoMessage() {}
func (x *Counts) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Counts.ProtoReflect.Descriptor instead.
func (*Counts) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{5}
}
func (x *Counts) GetFiles() int32 {
if x != nil {
return x.Files
}
return 0
}
func (x *Counts) GetDirectories() int32 {
if x != nil {
return x.Directories
}
return 0
}
func (x *Counts) GetSymlinks() int32 {
if x != nil {
return x.Symlinks
}
return 0
}
func (x *Counts) GetDeleted() int32 {
if x != nil {
return x.Deleted
}
return 0
}
func (x *Counts) GetBytes() int64 {
if x != nil {
return x.Bytes
}
return 0
}
func (x *Counts) GetSequence() int64 {
if x != nil {
return x.Sequence
}
return 0
}
func (x *Counts) GetDeviceId() []byte {
if x != nil {
return x.DeviceId
}
return nil
}
func (x *Counts) GetLocalFlags() uint32 {
if x != nil {
return x.LocalFlags
}
return 0
}
type CountsSet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Counts []*Counts `protobuf:"bytes,1,rep,name=counts,proto3" json:"counts,omitempty"`
Created int64 `protobuf:"varint,2,opt,name=created,proto3" json:"created,omitempty"` // unix nanos
}
func (x *CountsSet) Reset() {
*x = CountsSet{}
mi := &file_dbproto_structs_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CountsSet) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CountsSet) ProtoMessage() {}
func (x *CountsSet) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CountsSet.ProtoReflect.Descriptor instead.
func (*CountsSet) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{6}
}
func (x *CountsSet) GetCounts() []*Counts {
if x != nil {
return x.Counts
}
return nil
}
func (x *CountsSet) GetCreated() int64 {
if x != nil {
return x.Created
}
return 0
}
type ObservedFolder struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Time *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=time,proto3" json:"time,omitempty"`
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"`
ReceiveEncrypted bool `protobuf:"varint,3,opt,name=receive_encrypted,json=receiveEncrypted,proto3" json:"receive_encrypted,omitempty"`
RemoteEncrypted bool `protobuf:"varint,4,opt,name=remote_encrypted,json=remoteEncrypted,proto3" json:"remote_encrypted,omitempty"`
}
func (x *ObservedFolder) Reset() {
*x = ObservedFolder{}
mi := &file_dbproto_structs_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ObservedFolder) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ObservedFolder) ProtoMessage() {}
func (x *ObservedFolder) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ObservedFolder.ProtoReflect.Descriptor instead.
func (*ObservedFolder) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{7}
}
func (x *ObservedFolder) GetTime() *timestamppb.Timestamp {
if x != nil {
return x.Time
}
return nil
}
func (x *ObservedFolder) GetLabel() string {
if x != nil {
return x.Label
}
return ""
}
func (x *ObservedFolder) GetReceiveEncrypted() bool {
if x != nil {
return x.ReceiveEncrypted
}
return false
}
func (x *ObservedFolder) GetRemoteEncrypted() bool {
if x != nil {
return x.RemoteEncrypted
}
return false
}
type ObservedDevice struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Time *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=time,proto3" json:"time,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
}
func (x *ObservedDevice) Reset() {
*x = ObservedDevice{}
mi := &file_dbproto_structs_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ObservedDevice) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ObservedDevice) ProtoMessage() {}
func (x *ObservedDevice) ProtoReflect() protoreflect.Message {
mi := &file_dbproto_structs_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ObservedDevice.ProtoReflect.Descriptor instead.
func (*ObservedDevice) Descriptor() ([]byte, []int) {
return file_dbproto_structs_proto_rawDescGZIP(), []int{8}
}
func (x *ObservedDevice) GetTime() *timestamppb.Timestamp {
if x != nil {
return x.Time
}
return nil
}
func (x *ObservedDevice) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *ObservedDevice) GetAddress() string {
if x != nil {
return x.Address
}
return ""
}
var File_dbproto_structs_proto protoreflect.FileDescriptor
var file_dbproto_structs_proto_rawDesc = []byte{
0x0a, 0x15, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74,
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x1a, 0x0d, 0x62, 0x65, 0x70, 0x2f, 0x62, 0x65, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x22, 0xe5, 0x05, 0x0a, 0x11, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x54, 0x72, 0x75,
0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69,
0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d,
0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x18, 0x05, 0x20, 0x01,
0x28, 0x03, 0x52, 0x09, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x53, 0x12, 0x1f, 0x0a,
0x0b, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x0c, 0x20, 0x01,
0x28, 0x04, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x42, 0x79, 0x12, 0x25,
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x0b, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x76, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63,
0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63,
0x65, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x79, 0x6d, 0x6c, 0x69,
0x6e, 0x6b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x63,
0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x6e,
0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46, 0x69, 0x6c, 0x65,
0x49, 0x6e, 0x66, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x20,
0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18,
0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e,
0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x7a, 0x65,
0x12, 0x2d, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0e, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12,
0x20, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0xe8,
0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x6c, 0x61, 0x67,
0x73, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73,
0x68, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6e, 0x73, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52,
0x0d, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x73, 0x12, 0x37,
0x0a, 0x17, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x72, 0x61,
0x69, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28, 0x05,
0x52, 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x69,
0x6c, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x64, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01,
0x28, 0x08, 0x52, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6e,
0x6f, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20,
0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x73, 0x4a, 0x04, 0x08, 0x10, 0x10, 0x11, 0x22, 0x91, 0x01, 0x0a, 0x0b, 0x46, 0x69, 0x6c,
0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x65, 0x70, 0x2e,
0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x64,
0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, 0x69, 0x6e,
0x76, 0x61, 0x6c, 0x69, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3f, 0x0a, 0x0b,
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x76,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e,
0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x33, 0x0a,
0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x62, 0x6c,
0x6f, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x65, 0x70,
0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x73, 0x22, 0x5c, 0x0a, 0x15, 0x49, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c,
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0xe9, 0x07, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68,
0x22, 0xe6, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73,
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72,
0x69, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18,
0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x12,
0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05,
0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74,
0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12,
0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
0x03, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64,
0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08,
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x4e, 0x0a, 0x09, 0x43, 0x6f, 0x75,
0x6e, 0x74, 0x73, 0x53, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12,
0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0xae, 0x01, 0x0a, 0x0e, 0x4f, 0x62,
0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x04,
0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62,
0x65, 0x6c, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x6e,
0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72,
0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12,
0x29, 0x0a, 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70,
0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x6d, 0x6f, 0x74,
0x65, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x22, 0x6e, 0x0a, 0x0e, 0x4f, 0x62,
0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x04,
0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x8c, 0x01, 0x0a, 0x0b, 0x63,
0x6f, 0x6d, 0x2e, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x0c, 0x53, 0x74, 0x72, 0x75,
0x63, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67,
0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2,
0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xca,
0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xe2, 0x02, 0x13, 0x44, 0x62, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea,
0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
file_dbproto_structs_proto_rawDescOnce sync.Once
file_dbproto_structs_proto_rawDescData = file_dbproto_structs_proto_rawDesc
)
func file_dbproto_structs_proto_rawDescGZIP() []byte {
file_dbproto_structs_proto_rawDescOnce.Do(func() {
file_dbproto_structs_proto_rawDescData = protoimpl.X.CompressGZIP(file_dbproto_structs_proto_rawDescData)
})
return file_dbproto_structs_proto_rawDescData
}
var file_dbproto_structs_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_dbproto_structs_proto_goTypes = []any{
(*FileInfoTruncated)(nil), // 0: dbproto.FileInfoTruncated
(*FileVersion)(nil), // 1: dbproto.FileVersion
(*VersionList)(nil), // 2: dbproto.VersionList
(*BlockList)(nil), // 3: dbproto.BlockList
(*IndirectionHashesOnly)(nil), // 4: dbproto.IndirectionHashesOnly
(*Counts)(nil), // 5: dbproto.Counts
(*CountsSet)(nil), // 6: dbproto.CountsSet
(*ObservedFolder)(nil), // 7: dbproto.ObservedFolder
(*ObservedDevice)(nil), // 8: dbproto.ObservedDevice
(*bep.Vector)(nil), // 9: bep.Vector
(bep.FileInfoType)(0), // 10: bep.FileInfoType
(*bep.PlatformData)(nil), // 11: bep.PlatformData
(*bep.BlockInfo)(nil), // 12: bep.BlockInfo
(*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp
}
var file_dbproto_structs_proto_depIdxs = []int32{
9, // 0: dbproto.FileInfoTruncated.version:type_name -> bep.Vector
10, // 1: dbproto.FileInfoTruncated.type:type_name -> bep.FileInfoType
11, // 2: dbproto.FileInfoTruncated.platform:type_name -> bep.PlatformData
9, // 3: dbproto.FileVersion.version:type_name -> bep.Vector
1, // 4: dbproto.VersionList.versions:type_name -> dbproto.FileVersion
12, // 5: dbproto.BlockList.blocks:type_name -> bep.BlockInfo
5, // 6: dbproto.CountsSet.counts:type_name -> dbproto.Counts
13, // 7: dbproto.ObservedFolder.time:type_name -> google.protobuf.Timestamp
13, // 8: dbproto.ObservedDevice.time:type_name -> google.protobuf.Timestamp
9, // [9:9] is the sub-list for method output_type
9, // [9:9] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
}
func init() { file_dbproto_structs_proto_init() }
func file_dbproto_structs_proto_init() {
if File_dbproto_structs_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_dbproto_structs_proto_rawDesc,
NumEnums: 0,
NumMessages: 9,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_dbproto_structs_proto_goTypes,
DependencyIndexes: file_dbproto_structs_proto_depIdxs,
MessageInfos: file_dbproto_structs_proto_msgTypes,
}.Build()
File_dbproto_structs_proto = out.File
file_dbproto_structs_proto_rawDesc = nil
file_dbproto_structs_proto_goTypes = nil
file_dbproto_structs_proto_depIdxs = nil
}

View File

@@ -0,0 +1,155 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.1
// protoc (unknown)
// source: discoproto/local.proto
package discoproto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Announce struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Addresses []string `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"`
InstanceId int64 `protobuf:"varint,3,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"`
}
func (x *Announce) Reset() {
*x = Announce{}
mi := &file_discoproto_local_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Announce) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Announce) ProtoMessage() {}
func (x *Announce) ProtoReflect() protoreflect.Message {
mi := &file_discoproto_local_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Announce.ProtoReflect.Descriptor instead.
func (*Announce) Descriptor() ([]byte, []int) {
return file_discoproto_local_proto_rawDescGZIP(), []int{0}
}
func (x *Announce) GetId() []byte {
if x != nil {
return x.Id
}
return nil
}
func (x *Announce) GetAddresses() []string {
if x != nil {
return x.Addresses
}
return nil
}
func (x *Announce) GetInstanceId() int64 {
if x != nil {
return x.InstanceId
}
return 0
}
var File_discoproto_local_proto protoreflect.FileDescriptor
var file_discoproto_local_proto_rawDesc = []byte{
0x0a, 0x16, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x59, 0x0a, 0x08, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64,
0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20,
0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1f,
0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x03, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x42,
0x9c, 0x01, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x42, 0x0a, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x79, 0x6e,
0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67,
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x69,
0x73, 0x63, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02,
0x0a, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xca, 0x02, 0x0a, 0x44, 0x69,
0x73, 0x63, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xe2, 0x02, 0x16, 0x44, 0x69, 0x73, 0x63, 0x6f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
0x61, 0xea, 0x02, 0x0a, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_discoproto_local_proto_rawDescOnce sync.Once
file_discoproto_local_proto_rawDescData = file_discoproto_local_proto_rawDesc
)
func file_discoproto_local_proto_rawDescGZIP() []byte {
file_discoproto_local_proto_rawDescOnce.Do(func() {
file_discoproto_local_proto_rawDescData = protoimpl.X.CompressGZIP(file_discoproto_local_proto_rawDescData)
})
return file_discoproto_local_proto_rawDescData
}
var file_discoproto_local_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_discoproto_local_proto_goTypes = []any{
(*Announce)(nil), // 0: discoproto.Announce
}
var file_discoproto_local_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_discoproto_local_proto_init() }
func file_discoproto_local_proto_init() {
if File_discoproto_local_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_discoproto_local_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_discoproto_local_proto_goTypes,
DependencyIndexes: file_discoproto_local_proto_depIdxs,
MessageInfos: file_discoproto_local_proto_msgTypes,
}.Build()
File_discoproto_local_proto = out.File
file_discoproto_local_proto_rawDesc = nil
file_discoproto_local_proto_goTypes = nil
file_discoproto_local_proto_depIdxs = nil
}

View File

@@ -0,0 +1,276 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.1
// protoc (unknown)
// source: discosrv/discosrv.proto
package discosrv
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type DatabaseRecord struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Addresses []*DatabaseAddress `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"`
Seen int64 `protobuf:"varint,3,opt,name=seen,proto3" json:"seen,omitempty"` // Unix nanos, last device announce
}
func (x *DatabaseRecord) Reset() {
*x = DatabaseRecord{}
mi := &file_discosrv_discosrv_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DatabaseRecord) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DatabaseRecord) ProtoMessage() {}
func (x *DatabaseRecord) ProtoReflect() protoreflect.Message {
mi := &file_discosrv_discosrv_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DatabaseRecord.ProtoReflect.Descriptor instead.
func (*DatabaseRecord) Descriptor() ([]byte, []int) {
return file_discosrv_discosrv_proto_rawDescGZIP(), []int{0}
}
func (x *DatabaseRecord) GetAddresses() []*DatabaseAddress {
if x != nil {
return x.Addresses
}
return nil
}
func (x *DatabaseRecord) GetSeen() int64 {
if x != nil {
return x.Seen
}
return 0
}
type ReplicationRecord struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // raw 32 byte device ID
Addresses []*DatabaseAddress `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"`
Seen int64 `protobuf:"varint,3,opt,name=seen,proto3" json:"seen,omitempty"` // Unix nanos, last device announce
}
func (x *ReplicationRecord) Reset() {
*x = ReplicationRecord{}
mi := &file_discosrv_discosrv_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ReplicationRecord) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReplicationRecord) ProtoMessage() {}
func (x *ReplicationRecord) ProtoReflect() protoreflect.Message {
mi := &file_discosrv_discosrv_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReplicationRecord.ProtoReflect.Descriptor instead.
func (*ReplicationRecord) Descriptor() ([]byte, []int) {
return file_discosrv_discosrv_proto_rawDescGZIP(), []int{1}
}
func (x *ReplicationRecord) GetKey() []byte {
if x != nil {
return x.Key
}
return nil
}
func (x *ReplicationRecord) GetAddresses() []*DatabaseAddress {
if x != nil {
return x.Addresses
}
return nil
}
func (x *ReplicationRecord) GetSeen() int64 {
if x != nil {
return x.Seen
}
return 0
}
type DatabaseAddress struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
Expires int64 `protobuf:"varint,2,opt,name=expires,proto3" json:"expires,omitempty"` // Unix nanos
}
func (x *DatabaseAddress) Reset() {
*x = DatabaseAddress{}
mi := &file_discosrv_discosrv_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DatabaseAddress) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DatabaseAddress) ProtoMessage() {}
func (x *DatabaseAddress) ProtoReflect() protoreflect.Message {
mi := &file_discosrv_discosrv_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DatabaseAddress.ProtoReflect.Descriptor instead.
func (*DatabaseAddress) Descriptor() ([]byte, []int) {
return file_discosrv_discosrv_proto_rawDescGZIP(), []int{2}
}
func (x *DatabaseAddress) GetAddress() string {
if x != nil {
return x.Address
}
return ""
}
func (x *DatabaseAddress) GetExpires() int64 {
if x != nil {
return x.Expires
}
return 0
}
var File_discosrv_discosrv_proto protoreflect.FileDescriptor
var file_discosrv_discosrv_proto_rawDesc = []byte{
0x0a, 0x17, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x73, 0x72, 0x76, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f,
0x73, 0x72, 0x76, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x64, 0x69, 0x73, 0x63, 0x6f,
0x73, 0x72, 0x76, 0x22, 0x5d, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52,
0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x37, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f,
0x73, 0x72, 0x76, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x41, 0x64, 0x64, 0x72,
0x65, 0x73, 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12,
0x0a, 0x04, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x65,
0x65, 0x6e, 0x22, 0x72, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x09, 0x61, 0x64, 0x64,
0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64,
0x69, 0x73, 0x63, 0x6f, 0x73, 0x72, 0x76, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65,
0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
0x52, 0x04, 0x73, 0x65, 0x65, 0x6e, 0x22, 0x45, 0x0a, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61,
0x73, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64,
0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72,
0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x18, 0x02,
0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x42, 0x93, 0x01,
0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x73, 0x72, 0x76, 0x42, 0x0d,
0x44, 0x69, 0x73, 0x63, 0x6f, 0x73, 0x72, 0x76, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x79, 0x6e, 0x63,
0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x69, 0x73,
0x63, 0x6f, 0x73, 0x72, 0x76, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x44, 0x69,
0x73, 0x63, 0x6f, 0x73, 0x72, 0x76, 0xca, 0x02, 0x08, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x73, 0x72,
0x76, 0xe2, 0x02, 0x14, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x73, 0x72, 0x76, 0x5c, 0x47, 0x50, 0x42,
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x44, 0x69, 0x73, 0x63, 0x6f,
0x73, 0x72, 0x76, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_discosrv_discosrv_proto_rawDescOnce sync.Once
file_discosrv_discosrv_proto_rawDescData = file_discosrv_discosrv_proto_rawDesc
)
func file_discosrv_discosrv_proto_rawDescGZIP() []byte {
file_discosrv_discosrv_proto_rawDescOnce.Do(func() {
file_discosrv_discosrv_proto_rawDescData = protoimpl.X.CompressGZIP(file_discosrv_discosrv_proto_rawDescData)
})
return file_discosrv_discosrv_proto_rawDescData
}
var file_discosrv_discosrv_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_discosrv_discosrv_proto_goTypes = []any{
(*DatabaseRecord)(nil), // 0: discosrv.DatabaseRecord
(*ReplicationRecord)(nil), // 1: discosrv.ReplicationRecord
(*DatabaseAddress)(nil), // 2: discosrv.DatabaseAddress
}
var file_discosrv_discosrv_proto_depIdxs = []int32{
2, // 0: discosrv.DatabaseRecord.addresses:type_name -> discosrv.DatabaseAddress
2, // 1: discosrv.ReplicationRecord.addresses:type_name -> discosrv.DatabaseAddress
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_discosrv_discosrv_proto_init() }
func file_discosrv_discosrv_proto_init() {
if File_discosrv_discosrv_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_discosrv_discosrv_proto_rawDesc,
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_discosrv_discosrv_proto_goTypes,
DependencyIndexes: file_discosrv_discosrv_proto_depIdxs,
MessageInfos: file_discosrv_discosrv_proto_msgTypes,
}.Build()
File_discosrv_discosrv_proto = out.File
file_discosrv_discosrv_proto_rawDesc = nil
file_discosrv_discosrv_proto_goTypes = nil
file_discosrv_discosrv_proto_depIdxs = nil
}

View File

@@ -0,0 +1,24 @@
package protoutil
import (
"fmt"
"google.golang.org/protobuf/proto"
)
func MarshalTo(buf []byte, pb proto.Message) (int, error) {
if sz := proto.Size(pb); len(buf) < sz {
return 0, fmt.Errorf("buffer too small")
} else if sz == 0 {
return 0, nil
}
opts := proto.MarshalOptions{}
bs, err := opts.MarshalAppend(buf[:0], pb)
if err != nil {
return 0, err
}
if &buf[0] != &bs[0] {
panic("can't happen: slice was reallocated")
}
return len(bs), nil
}

View File

@@ -402,6 +402,9 @@ func (s *service) Serve(ctx context.Context) error {
// care about we log ourselves from the handlers.
ErrorLog: log.New(io.Discard, "", 0),
}
if shouldDebugHTTP() {
srv.ErrorLog = log.Default()
}
l.Infoln("GUI and API listening on", listener.Addr())
l.Infoln("Access the GUI via the following URL:", guiCfg.URL())
@@ -1165,6 +1168,7 @@ type fileEntry struct {
func (s *service) getSupportBundle(w http.ResponseWriter, r *http.Request) {
var files []fileEntry
const profilingDuration = 4 * time.Second
// Redacted configuration as a JSON
if jsonConfig, err := json.MarshalIndent(getRedactedConfig(s), "", " "); err != nil {
@@ -1231,10 +1235,10 @@ func (s *service) getSupportBundle(w http.ResponseWriter, r *http.Request) {
}
// Metrics data as text
buf := bytes.NewBuffer(nil)
wr := bufferedResponseWriter{Writer: buf}
var metricsBuf bytes.Buffer
wr := bufferedResponseWriter{Writer: &metricsBuf}
promhttp.Handler().ServeHTTP(wr, &http.Request{Method: http.MethodGet})
files = append(files, fileEntry{name: "metrics.txt", data: buf.Bytes()})
files = append(files, fileEntry{name: "metrics.txt", data: metricsBuf.Bytes()})
// Connection data as JSON
connStats := s.model.ConnectionStats()
@@ -1244,20 +1248,42 @@ func (s *service) getSupportBundle(w http.ResponseWriter, r *http.Request) {
files = append(files, fileEntry{name: "connection-stats.json.txt", data: connStatsJSON})
}
// Heap and CPU Proofs as a pprof extension
var heapBuffer, cpuBuffer bytes.Buffer
filename := fmt.Sprintf("syncthing-heap-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, build.Version, time.Now().Format("150405")) // hhmmss
runtime.GC()
if err := pprof.WriteHeapProfile(&heapBuffer); err == nil {
files = append(files, fileEntry{name: filename, data: heapBuffer.Bytes()})
// Write a goroutine profile
if p := pprof.Lookup("goroutine"); p != nil {
var goroutineBuf bytes.Buffer
_ = p.WriteTo(&goroutineBuf, 0)
filename := fmt.Sprintf("syncthing-goroutines-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, build.Version, time.Now().Format("150405")) // hhmmss
files = append(files, fileEntry{name: filename, data: goroutineBuf.Bytes()})
}
const duration = 4 * time.Second
filename = fmt.Sprintf("syncthing-cpu-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, build.Version, time.Now().Format("150405")) // hhmmss
if err := pprof.StartCPUProfile(&cpuBuffer); err == nil {
time.Sleep(duration)
// Take a heap profile
var heapBuf bytes.Buffer
runtime.GC()
if err := pprof.WriteHeapProfile(&heapBuf); err == nil {
filename := fmt.Sprintf("syncthing-heap-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, build.Version, time.Now().Format("150405")) // hhmmss
files = append(files, fileEntry{name: filename, data: heapBuf.Bytes()})
}
// Enable block profiling
runtime.SetBlockProfileRate(1)
defer runtime.SetBlockProfileRate(0)
// Take a CPU profile, waiting for the profiling duration. This also
// gives time for the block profile.
var cpuBuf bytes.Buffer
if err := pprof.StartCPUProfile(&cpuBuf); err == nil {
time.Sleep(profilingDuration)
pprof.StopCPUProfile()
files = append(files, fileEntry{name: filename, data: cpuBuffer.Bytes()})
filename := fmt.Sprintf("syncthing-cpu-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, build.Version, time.Now().Format("150405")) // hhmmss
files = append(files, fileEntry{name: filename, data: cpuBuf.Bytes()})
}
// Write the block profile
if p := pprof.Lookup("block"); p != nil {
var blockBuf bytes.Buffer
_ = p.WriteTo(&blockBuf, 0)
filename := fmt.Sprintf("syncthing-block-%s-%s-%s-%s.pprof", runtime.GOOS, runtime.GOARCH, build.Version, time.Now().Format("150405")) // hhmmss
files = append(files, fileEntry{name: filename, data: blockBuf.Bytes()})
}
// Add buffer files to buffer zip
@@ -1483,7 +1509,7 @@ func (*service) getDeviceID(w http.ResponseWriter, r *http.Request) {
func (*service) getLang(w http.ResponseWriter, r *http.Request) {
lang := r.Header.Get("Accept-Language")
var weights = make(map[string]float64)
weights := make(map[string]float64)
for _, l := range strings.Split(lang, ",") {
parts := strings.SplitN(l, ";", 2)
code := strings.ToLower(strings.TrimSpace(parts[0]))
@@ -1502,7 +1528,7 @@ func (*service) getLang(w http.ResponseWriter, r *http.Request) {
weights[code] = q
}
}
var langs = make([]string, 0, len(weights))
langs := make([]string, 0, len(weights))
for code := range weights {
langs = append(langs, code)
}
@@ -1725,10 +1751,10 @@ func (*service) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
current := qs.Get("current")
// Default value or in case of error unmarshalling ends up being basic fs.
var fsType fs.FilesystemType
var fsType config.FilesystemType
fsType.UnmarshalText([]byte(qs.Get("filesystem")))
sendJSON(w, browse(fsType, current))
sendJSON(w, browse(fsType.ToFS(), current))
}
func browse(fsType fs.FilesystemType, current string) []string {
@@ -1847,10 +1873,10 @@ func (*service) getHeapProf(w http.ResponseWriter, _ *http.Request) {
pprof.WriteHeapProfile(w)
}
func toJsonFileInfoSlice(fs []db.FileInfoTruncated) []jsonFileInfoTrunc {
res := make([]jsonFileInfoTrunc, len(fs))
func toJsonFileInfoSlice(fs []protocol.FileInfo) []jsonFileInfo {
res := make([]jsonFileInfo, len(fs))
for i, f := range fs {
res[i] = jsonFileInfoTrunc(f)
res[i] = jsonFileInfo(f)
}
return res
}
@@ -1865,15 +1891,7 @@ func (f jsonFileInfo) MarshalJSON() ([]byte, error) {
return json.Marshal(m)
}
type jsonFileInfoTrunc db.FileInfoTruncated
func (f jsonFileInfoTrunc) MarshalJSON() ([]byte, error) {
m := fileIntfJSONMap(db.FileInfoTruncated(f))
m["numBlocks"] = nil // explicitly unknown
return json.Marshal(m)
}
func fileIntfJSONMap(f protocol.FileIntf) map[string]interface{} {
func fileIntfJSONMap(f protocol.FileInfo) map[string]interface{} {
out := map[string]interface{}{
"name": f.FileName(),
"type": f.FileType().String(),

View File

@@ -25,6 +25,8 @@ import (
"time"
"github.com/d4l3k/messagediff"
"github.com/thejerf/suture/v4"
"github.com/syncthing/syncthing/lib/assets"
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/config"
@@ -46,7 +48,6 @@ import (
"github.com/syncthing/syncthing/lib/sync"
"github.com/syncthing/syncthing/lib/tlsutil"
"github.com/syncthing/syncthing/lib/ur"
"github.com/thejerf/suture/v4"
)
var (

View File

@@ -12,6 +12,9 @@ import (
"strings"
"time"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/apiproto"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/events"
@@ -28,16 +31,17 @@ type tokenManager struct {
timeNow func() time.Time // can be overridden for testing
mut sync.Mutex
tokens *TokenSet
tokens *apiproto.TokenSet
saveTimer *time.Timer
}
func newTokenManager(key string, miscDB *db.NamespacedKV, lifetime time.Duration, maxItems int) *tokenManager {
tokens := &TokenSet{
Tokens: make(map[string]int64),
}
var tokens apiproto.TokenSet
if bs, ok, _ := miscDB.Bytes(key); ok {
_ = tokens.Unmarshal(bs) // best effort
_ = proto.Unmarshal(bs, &tokens) // best effort
}
if tokens.Tokens == nil {
tokens.Tokens = make(map[string]int64)
}
return &tokenManager{
key: key,
@@ -46,7 +50,7 @@ func newTokenManager(key string, miscDB *db.NamespacedKV, lifetime time.Duration
maxItems: maxItems,
timeNow: time.Now,
mut: sync.NewMutex(),
tokens: tokens,
tokens: &tokens,
}
}
@@ -136,7 +140,7 @@ func (m *tokenManager) scheduledSave() {
m.saveTimer = nil
bs, _ := m.tokens.Marshal() // can't fail
bs, _ := proto.Marshal(m.tokens) // can't fail
_ = m.miscDB.PutBytes(m.key, bs) // can fail, but what are we going to do?
}

View File

@@ -1,411 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/api/tokenset.proto
package api
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type TokenSet struct {
// token -> expiry time (epoch nanoseconds)
Tokens map[string]int64 `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens" xml:"token" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
}
func (m *TokenSet) Reset() { *m = TokenSet{} }
func (m *TokenSet) String() string { return proto.CompactTextString(m) }
func (*TokenSet) ProtoMessage() {}
func (*TokenSet) Descriptor() ([]byte, []int) {
return fileDescriptor_9ea8707737c33b38, []int{0}
}
func (m *TokenSet) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *TokenSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_TokenSet.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *TokenSet) XXX_Merge(src proto.Message) {
xxx_messageInfo_TokenSet.Merge(m, src)
}
func (m *TokenSet) XXX_Size() int {
return m.ProtoSize()
}
func (m *TokenSet) XXX_DiscardUnknown() {
xxx_messageInfo_TokenSet.DiscardUnknown(m)
}
var xxx_messageInfo_TokenSet proto.InternalMessageInfo
func init() {
proto.RegisterType((*TokenSet)(nil), "api.TokenSet")
proto.RegisterMapType((map[string]int64)(nil), "api.TokenSet.TokensEntry")
}
func init() { proto.RegisterFile("lib/api/tokenset.proto", fileDescriptor_9ea8707737c33b38) }
var fileDescriptor_9ea8707737c33b38 = []byte{
// 260 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcb, 0xc9, 0x4c, 0xd2,
0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0xc9, 0xcf, 0x4e, 0xcd, 0x2b, 0x4e, 0x2d, 0xd1, 0x2b, 0x28, 0xca,
0x2f, 0xc9, 0x17, 0x62, 0x4e, 0x2c, 0xc8, 0x54, 0x3a, 0xce, 0xc8, 0xc5, 0x11, 0x02, 0x12, 0x0f,
0x4e, 0x2d, 0x11, 0x0a, 0xe0, 0x62, 0x83, 0xa8, 0x91, 0x60, 0x54, 0x60, 0xd6, 0xe0, 0x36, 0x92,
0xd4, 0x4b, 0x2c, 0xc8, 0xd4, 0x83, 0x49, 0x43, 0x18, 0xc5, 0xae, 0x79, 0x25, 0x45, 0x95, 0x4e,
0xb2, 0x27, 0xee, 0xc9, 0x33, 0xbc, 0xba, 0x27, 0x0f, 0xd5, 0xf0, 0xe9, 0x9e, 0x3c, 0x77, 0x45,
0x6e, 0x8e, 0x95, 0x12, 0x98, 0xab, 0x14, 0x04, 0x15, 0x96, 0xca, 0xe4, 0xe2, 0x46, 0xd2, 0x25,
0xa4, 0xc6, 0xc5, 0x9c, 0x9d, 0x5a, 0x29, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe9, 0x24, 0xf2, 0xea,
0x9e, 0x3c, 0x88, 0xfb, 0xe9, 0x9e, 0x3c, 0x27, 0x58, 0x6f, 0x76, 0x6a, 0xa5, 0x52, 0x10, 0x48,
0x44, 0x48, 0x8f, 0x8b, 0xb5, 0x2c, 0x31, 0xa7, 0x34, 0x55, 0x82, 0x49, 0x81, 0x51, 0x83, 0xd9,
0x49, 0xe2, 0xd5, 0x3d, 0x79, 0x88, 0x00, 0xdc, 0x1e, 0x30, 0x4f, 0x29, 0x08, 0x22, 0x6a, 0xc5,
0x64, 0xc1, 0xe8, 0xe4, 0x71, 0xe2, 0xa1, 0x1c, 0xc3, 0x85, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9,
0x31, 0x5e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x82, 0xc7, 0x72, 0x8c, 0x17, 0x1e,
0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x96, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97,
0x9c, 0x9f, 0xab, 0x5f, 0x5c, 0x99, 0x97, 0x5c, 0x92, 0x91, 0x99, 0x97, 0x8e, 0xc4, 0x82, 0x86,
0x53, 0x12, 0x1b, 0x38, 0x7c, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x25, 0x31, 0x49,
0x39, 0x01, 0x00, 0x00,
}
func (m *TokenSet) Marshal() (dAtA []byte, err error) {
size := m.ProtoSize()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *TokenSet) MarshalTo(dAtA []byte) (int, error) {
size := m.ProtoSize()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *TokenSet) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Tokens) > 0 {
for k := range m.Tokens {
v := m.Tokens[k]
baseI := i
i = encodeVarintTokenset(dAtA, i, uint64(v))
i--
dAtA[i] = 0x10
i -= len(k)
copy(dAtA[i:], k)
i = encodeVarintTokenset(dAtA, i, uint64(len(k)))
i--
dAtA[i] = 0xa
i = encodeVarintTokenset(dAtA, i, uint64(baseI-i))
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintTokenset(dAtA []byte, offset int, v uint64) int {
offset -= sovTokenset(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *TokenSet) ProtoSize() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Tokens) > 0 {
for k, v := range m.Tokens {
_ = k
_ = v
mapEntrySize := 1 + len(k) + sovTokenset(uint64(len(k))) + 1 + sovTokenset(uint64(v))
n += mapEntrySize + 1 + sovTokenset(uint64(mapEntrySize))
}
}
return n
}
func sovTokenset(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozTokenset(x uint64) (n int) {
return sovTokenset(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *TokenSet) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTokenset
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: TokenSet: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TokenSet: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Tokens", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTokenset
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTokenset
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthTokenset
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Tokens == nil {
m.Tokens = make(map[string]int64)
}
var mapkey string
var mapvalue int64
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTokenset
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTokenset
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthTokenset
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey < 0 {
return ErrInvalidLengthTokenset
}
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
} else if fieldNum == 2 {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTokenset
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapvalue |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
} else {
iNdEx = entryPreIndex
skippy, err := skipTokenset(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTokenset
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
m.Tokens[mapkey] = mapvalue
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTokenset(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthTokenset
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTokenset(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTokenset
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTokenset
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowTokenset
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthTokenset
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupTokenset
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthTokenset
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthTokenset = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowTokenset = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupTokenset = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -148,7 +148,7 @@ func readBroadcasts(ctx context.Context, outbox chan<- recv, port int) error {
}
func bcast(ip *net.IPNet) *net.IPNet {
var bc = &net.IPNet{}
bc := &net.IPNet{}
bc.IP = make([]byte, len(ip.IP))
copy(bc.IP, ip.IP)
bc.Mask = ip.Mask

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("beacon", "Multicast and broadcast discovery")
)
var l = logger.DefaultLogger.NewFacility("beacon", "Multicast and broadcast discovery")

View File

@@ -6,6 +6,13 @@
package config
type AuthMode int32
const (
AuthModeStatic AuthMode = 0
AuthModeLDAP AuthMode = 1
)
func (t AuthMode) String() string {
switch t {
case AuthModeStatic:

View File

@@ -1,69 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/authmode.proto
package config
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
_ "github.com/syncthing/syncthing/proto/ext"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type AuthMode int32
const (
AuthModeStatic AuthMode = 0
AuthModeLDAP AuthMode = 1
)
var AuthMode_name = map[int32]string{
0: "AUTH_MODE_STATIC",
1: "AUTH_MODE_LDAP",
}
var AuthMode_value = map[string]int32{
"AUTH_MODE_STATIC": 0,
"AUTH_MODE_LDAP": 1,
}
func (AuthMode) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_8e30b562e1bcea1e, []int{0}
}
func init() {
proto.RegisterEnum("config.AuthMode", AuthMode_name, AuthMode_value)
}
func init() { proto.RegisterFile("lib/config/authmode.proto", fileDescriptor_8e30b562e1bcea1e) }
var fileDescriptor_8e30b562e1bcea1e = []byte{
// 234 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0xc9, 0x4c, 0xd2,
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0x2c, 0x2d, 0xc9, 0xc8, 0xcd, 0x4f, 0x49, 0xd5,
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x08, 0x4b, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17,
0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2,
0x58, 0x8a, 0x33, 0xb5, 0xa2, 0x04, 0xc2, 0xd4, 0x2a, 0xe0, 0xe2, 0x70, 0x2c, 0x2d, 0xc9, 0xf0,
0xcd, 0x4f, 0x49, 0x15, 0xd2, 0xe0, 0x12, 0x70, 0x0c, 0x0d, 0xf1, 0x88, 0xf7, 0xf5, 0x77, 0x71,
0x8d, 0x0f, 0x0e, 0x71, 0x0c, 0xf1, 0x74, 0x16, 0x60, 0x90, 0x12, 0xea, 0x9a, 0xab, 0xc0, 0x07,
0x53, 0x13, 0x5c, 0x92, 0x58, 0x92, 0x99, 0x2c, 0x64, 0xc2, 0xc5, 0x87, 0x50, 0xe9, 0xe3, 0xe2,
0x18, 0x20, 0xc0, 0x28, 0xa5, 0xd0, 0x35, 0x57, 0x81, 0x07, 0xa6, 0x0e, 0x24, 0x76, 0xa9, 0x4f,
0x15, 0x85, 0x2f, 0xc5, 0xb2, 0x62, 0x89, 0x1c, 0x83, 0x93, 0xf7, 0x89, 0x87, 0x72, 0x0c, 0x17,
0x1e, 0xca, 0x31, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c,
0x0b, 0x1e, 0xcb, 0x31, 0x5e, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x66, 0x7a,
0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x71, 0x65, 0x5e, 0x72, 0x49, 0x46,
0x66, 0x5e, 0x3a, 0x12, 0x0b, 0x11, 0x0a, 0x49, 0x6c, 0x60, 0x5f, 0x18, 0x03, 0x02, 0x00, 0x00,
0xff, 0xff, 0x48, 0x80, 0x1f, 0x0c, 0x1a, 0x01, 0x00, 0x00,
}

View File

@@ -6,6 +6,14 @@
package config
type BlockPullOrder int32
const (
BlockPullOrderStandard BlockPullOrder = 0
BlockPullOrderRandom BlockPullOrder = 1
BlockPullOrderInOrder BlockPullOrder = 2
)
func (o BlockPullOrder) String() string {
switch o {
case BlockPullOrderStandard:

View File

@@ -1,73 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/blockpullorder.proto
package config
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type BlockPullOrder int32
const (
BlockPullOrderStandard BlockPullOrder = 0
BlockPullOrderRandom BlockPullOrder = 1
BlockPullOrderInOrder BlockPullOrder = 2
)
var BlockPullOrder_name = map[int32]string{
0: "BLOCK_PULL_ORDER_STANDARD",
1: "BLOCK_PULL_ORDER_RANDOM",
2: "BLOCK_PULL_ORDER_IN_ORDER",
}
var BlockPullOrder_value = map[string]int32{
"BLOCK_PULL_ORDER_STANDARD": 0,
"BLOCK_PULL_ORDER_RANDOM": 1,
"BLOCK_PULL_ORDER_IN_ORDER": 2,
}
func (BlockPullOrder) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_3c46a5289006da6c, []int{0}
}
func init() {
proto.RegisterEnum("config.BlockPullOrder", BlockPullOrder_name, BlockPullOrder_value)
}
func init() { proto.RegisterFile("lib/config/blockpullorder.proto", fileDescriptor_3c46a5289006da6c) }
var fileDescriptor_3c46a5289006da6c = []byte{
// 271 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcf, 0xc9, 0x4c, 0xd2,
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xca, 0xc9, 0x4f, 0xce, 0x2e, 0x28, 0xcd, 0xc9,
0xc9, 0x2f, 0x4a, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x4a,
0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3,
0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0xeb, 0x10, 0x23, 0x17, 0x9f, 0x13, 0xc8, 0x94, 0x80,
0xd2, 0x9c, 0x1c, 0x7f, 0x90, 0x29, 0x42, 0x96, 0x5c, 0x92, 0x4e, 0x3e, 0xfe, 0xce, 0xde, 0xf1,
0x01, 0xa1, 0x3e, 0x3e, 0xf1, 0xfe, 0x41, 0x2e, 0xae, 0x41, 0xf1, 0xc1, 0x21, 0x8e, 0x7e, 0x2e,
0x8e, 0x41, 0x2e, 0x02, 0x0c, 0x52, 0x52, 0x5d, 0x73, 0x15, 0xc4, 0x50, 0xb5, 0x04, 0x97, 0x24,
0xe6, 0xa5, 0x24, 0x16, 0xa5, 0x08, 0x99, 0x72, 0x89, 0x63, 0x68, 0x0d, 0x72, 0xf4, 0x73, 0xf1,
0xf7, 0x15, 0x60, 0x94, 0x92, 0xe8, 0x9a, 0xab, 0x20, 0x82, 0xaa, 0x31, 0x28, 0x31, 0x2f, 0x25,
0x3f, 0x57, 0xc8, 0x02, 0x8b, 0x8d, 0x9e, 0x7e, 0x10, 0x86, 0x00, 0x93, 0x94, 0x64, 0xd7, 0x5c,
0x05, 0x51, 0x54, 0x8d, 0x9e, 0x79, 0x60, 0x4a, 0x8a, 0x65, 0xc5, 0x12, 0x39, 0x06, 0x27, 0xef,
0x13, 0x0f, 0xe5, 0x18, 0x2e, 0x3c, 0x94, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39,
0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x16, 0x3c, 0x96, 0x63, 0xbc, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63,
0x39, 0x86, 0x28, 0xcd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xe2,
0xca, 0xbc, 0xe4, 0x92, 0x8c, 0xcc, 0xbc, 0x74, 0x24, 0x16, 0x22, 0x4c, 0x93, 0xd8, 0xc0, 0x01,
0x63, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x0c, 0xb7, 0x46, 0x68, 0x01, 0x00, 0x00,
}

View File

@@ -18,6 +18,7 @@ type requiresRestart struct {
func (requiresRestart) VerifyConfiguration(_, _ Configuration) error {
return nil
}
func (c requiresRestart) CommitConfiguration(_, _ Configuration) bool {
select {
case c.committed <- struct{}{}:
@@ -25,6 +26,7 @@ func (c requiresRestart) CommitConfiguration(_, _ Configuration) bool {
}
return false
}
func (requiresRestart) String() string {
return "requiresRestart"
}
@@ -34,9 +36,11 @@ type validationError struct{}
func (validationError) VerifyConfiguration(_, _ Configuration) error {
return errors.New("some error")
}
func (validationError) CommitConfiguration(_, _ Configuration) bool {
return true
}
func (validationError) String() string {
return "validationError"
}

58
lib/config/compression.go Normal file
View File

@@ -0,0 +1,58 @@
// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package config
import (
"github.com/syncthing/syncthing/lib/protocol"
)
type Compression int32
const (
CompressionMetadata Compression = 0
CompressionNever Compression = 1
CompressionAlways Compression = 2
)
var compressionMarshal = map[Compression]string{
CompressionNever: "never",
CompressionMetadata: "metadata",
CompressionAlways: "always",
}
var compressionUnmarshal = map[string]Compression{
// Legacy
"false": CompressionNever,
"true": CompressionMetadata,
// Current
"never": CompressionNever,
"metadata": CompressionMetadata,
"always": CompressionAlways,
}
func (c Compression) MarshalText() ([]byte, error) {
return []byte(compressionMarshal[c]), nil
}
func (c *Compression) UnmarshalText(bs []byte) error {
*c = compressionUnmarshal[string(bs)]
return nil
}
func (c Compression) ToProtocol() protocol.Compression {
switch c {
case CompressionNever:
return protocol.CompressionNever
case CompressionAlways:
return protocol.CompressionAlways
case CompressionMetadata:
return protocol.CompressionMetadata
default:
return protocol.CompressionMetadata
}
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2015 The Protocol Authors.
package protocol
package config
import "testing"

View File

@@ -49,7 +49,6 @@ var (
"dynamic+https://relays.syncthing.net/endpoint",
netutil.AddressURL("quic", net.JoinHostPort("0.0.0.0", strconv.Itoa(DefaultQUICPort))),
}
DefaultGUIPort = 8384
// DefaultDiscoveryServersV4 should be substituted when the configuration
// contains <globalAnnounceServer>default-v4</globalAnnounceServer>.
DefaultDiscoveryServersV4 = []string{
@@ -79,8 +78,10 @@ var (
"stun.counterpath.com:3478",
"stun.counterpath.net:3478",
"stun.ekiga.net:3478",
"stun.hitv.com:3478",
"stun.ideasip.com:3478",
"stun.internetcalls.com:3478",
"stun.miwifi.com:3478",
"stun.schlund.de:3478",
"stun.sipgate.net:10000",
"stun.sipgate.net:3478",
@@ -98,6 +99,28 @@ var (
errFolderPathEmpty = errors.New("folder has empty path")
)
type Configuration struct {
Version int `json:"version" xml:"version,attr"`
Folders []FolderConfiguration `json:"folders" xml:"folder"`
Devices []DeviceConfiguration `json:"devices" xml:"device"`
GUI GUIConfiguration `json:"gui" xml:"gui"`
LDAP LDAPConfiguration `json:"ldap" xml:"ldap"`
Options OptionsConfiguration `json:"options" xml:"options"`
IgnoredDevices []ObservedDevice `json:"remoteIgnoredDevices" xml:"remoteIgnoredDevice"`
DeprecatedPendingDevices []ObservedDevice `json:"-" xml:"pendingDevice,omitempty"` // Deprecated: Do not use.
Defaults Defaults `json:"defaults" xml:"defaults"`
}
type Defaults struct {
Folder FolderConfiguration `json:"folder" xml:"folder"`
Device DeviceConfiguration `json:"device" xml:"device"`
Ignores Ignores `json:"ignores" xml:"ignores"`
}
type Ignores struct {
Lines []string `json:"lines" xml:"line"`
}
func New(myID protocol.DeviceID) Configuration {
var cfg Configuration
cfg.Version = CurrentVersion
@@ -116,13 +139,23 @@ func New(myID protocol.DeviceID) Configuration {
}
func (cfg *Configuration) ProbeFreePorts() error {
port, err := getFreePort("127.0.0.1", DefaultGUIPort)
if err != nil {
return fmt.Errorf("get free port (GUI): %w", err)
if cfg.GUI.Network() == "tcp" {
guiHost, guiPort, err := net.SplitHostPort(cfg.GUI.Address())
if err != nil {
return fmt.Errorf("get default port (GUI): %w", err)
}
port, err := strconv.Atoi(guiPort)
if err != nil {
return fmt.Errorf("convert default port (GUI): %w", err)
}
port, err = getFreePort(guiHost, port)
if err != nil {
return fmt.Errorf("get free port (GUI): %w", err)
}
cfg.GUI.RawAddress = net.JoinHostPort(guiHost, strconv.Itoa(port))
}
cfg.GUI.RawAddress = fmt.Sprintf("127.0.0.1:%d", port)
port, err = getFreePort("0.0.0.0", DefaultTCPPort)
port, err := getFreePort("0.0.0.0", DefaultTCPPort)
if err != nil {
return fmt.Errorf("get free port (BEP): %w", err)
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -100,7 +100,7 @@ func TestDefaultValues(t *testing.T) {
},
Defaults: Defaults{
Folder: FolderConfiguration{
FilesystemType: fs.FilesystemTypeBasic,
FilesystemType: FilesystemTypeBasic,
Path: "~",
Type: FolderTypeSendReceive,
Devices: []FolderDeviceConfiguration{{DeviceID: device1}},
@@ -127,7 +127,7 @@ func TestDefaultValues(t *testing.T) {
Device: DeviceConfiguration{
Addresses: []string{"dynamic"},
AllowedNetworks: []string{},
Compression: protocol.CompressionMetadata,
Compression: CompressionMetadata,
IgnoredFolders: []ObservedFolder{},
},
Ignores: Ignores{
@@ -175,7 +175,7 @@ func TestDeviceConfig(t *testing.T) {
expectedFolders := []FolderConfiguration{
{
ID: "test",
FilesystemType: fs.FilesystemTypeBasic,
FilesystemType: FilesystemTypeBasic,
Path: "testdata",
Devices: []FolderDeviceConfiguration{{DeviceID: device1}, {DeviceID: device4}},
Type: FolderTypeSendOnly,
@@ -205,7 +205,7 @@ func TestDeviceConfig(t *testing.T) {
DeviceID: device1,
Name: "node one",
Addresses: []string{"tcp://a"},
Compression: protocol.CompressionMetadata,
Compression: CompressionMetadata,
AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{},
},
@@ -213,7 +213,7 @@ func TestDeviceConfig(t *testing.T) {
DeviceID: device4,
Name: "node two",
Addresses: []string{"tcp://b"},
Compression: protocol.CompressionMetadata,
Compression: CompressionMetadata,
AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{},
},
@@ -344,7 +344,7 @@ func TestDeviceAddressesDynamic(t *testing.T) {
DeviceID: device4,
Name: name, // Set when auto created
Addresses: []string{"dynamic"},
Compression: protocol.CompressionMetadata,
Compression: CompressionMetadata,
AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{},
},
@@ -368,21 +368,21 @@ func TestDeviceCompression(t *testing.T) {
device1: {
DeviceID: device1,
Addresses: []string{"dynamic"},
Compression: protocol.CompressionMetadata,
Compression: CompressionMetadata,
AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{},
},
device2: {
DeviceID: device2,
Addresses: []string{"dynamic"},
Compression: protocol.CompressionMetadata,
Compression: CompressionMetadata,
AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{},
},
device3: {
DeviceID: device3,
Addresses: []string{"dynamic"},
Compression: protocol.CompressionNever,
Compression: CompressionNever,
AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{},
},
@@ -390,7 +390,7 @@ func TestDeviceCompression(t *testing.T) {
DeviceID: device4,
Name: name, // Set when auto created
Addresses: []string{"dynamic"},
Compression: protocol.CompressionMetadata,
Compression: CompressionMetadata,
AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{},
},
@@ -433,7 +433,7 @@ func TestDeviceAddressesStatic(t *testing.T) {
DeviceID: device4,
Name: name, // Set when auto created
Addresses: []string{"dynamic"},
Compression: protocol.CompressionMetadata,
Compression: CompressionMetadata,
AllowedNetworks: []string{},
IgnoredFolders: []ObservedFolder{},
},
@@ -556,7 +556,7 @@ func TestFolderCheckPath(t *testing.T) {
for _, testcase := range testcases {
cfg := FolderConfiguration{
FilesystemType: fs.FilesystemTypeFake,
FilesystemType: FilesystemTypeFake,
MarkerName: DefaultMarkerName,
}
@@ -1281,7 +1281,7 @@ func adjustDeviceConfiguration(cfg *DeviceConfiguration, id protocol.DeviceID, n
func adjustFolderConfiguration(cfg *FolderConfiguration, id, label string, fsType fs.FilesystemType, path string) {
cfg.ID = id
cfg.Label = label
cfg.FilesystemType = fsType
cfg.FilesystemType = FilesystemType(fsType)
cfg.Path = path
}

View File

@@ -0,0 +1,86 @@
// Copyright (C) 2020 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package config
import "github.com/syncthing/syncthing/lib/fs"
type CopyRangeMethod int32
const (
CopyRangeMethodStandard CopyRangeMethod = 0
CopyRangeMethodIoctl CopyRangeMethod = 1
CopyRangeMethodCopyFileRange CopyRangeMethod = 2
CopyRangeMethodSendFile CopyRangeMethod = 3
CopyRangeMethodDuplicateExtents CopyRangeMethod = 4
CopyRangeMethodAllWithFallback CopyRangeMethod = 5
)
func (o CopyRangeMethod) String() string {
switch o {
case CopyRangeMethodStandard:
return "standard"
case CopyRangeMethodIoctl:
return "ioctl"
case CopyRangeMethodCopyFileRange:
return "copy_file_range"
case CopyRangeMethodSendFile:
return "sendfile"
case CopyRangeMethodDuplicateExtents:
return "duplicate_extents"
case CopyRangeMethodAllWithFallback:
return "all"
default:
return "unknown"
}
}
func (o CopyRangeMethod) ToFS() fs.CopyRangeMethod {
switch o {
case CopyRangeMethodStandard:
return fs.CopyRangeMethodStandard
case CopyRangeMethodIoctl:
return fs.CopyRangeMethodIoctl
case CopyRangeMethodCopyFileRange:
return fs.CopyRangeMethodCopyFileRange
case CopyRangeMethodSendFile:
return fs.CopyRangeMethodSendFile
case CopyRangeMethodDuplicateExtents:
return fs.CopyRangeMethodDuplicateExtents
case CopyRangeMethodAllWithFallback:
return fs.CopyRangeMethodAllWithFallback
default:
return fs.CopyRangeMethodStandard
}
}
func (o CopyRangeMethod) MarshalText() ([]byte, error) {
return []byte(o.String()), nil
}
func (o *CopyRangeMethod) UnmarshalText(bs []byte) error {
switch string(bs) {
case "standard":
*o = CopyRangeMethodStandard
case "ioctl":
*o = CopyRangeMethodIoctl
case "copy_file_range":
*o = CopyRangeMethodCopyFileRange
case "sendfile":
*o = CopyRangeMethodSendFile
case "duplicate_extents":
*o = CopyRangeMethodDuplicateExtents
case "all":
*o = CopyRangeMethodAllWithFallback
default:
*o = CopyRangeMethodStandard
}
return nil
}
func (o *CopyRangeMethod) ParseDefault(str string) error {
return o.UnmarshalText([]byte(str))
}

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("config", "Configuration loading and saving")
)
var l = logger.DefaultLogger.NewFacility("config", "Configuration loading and saving")

View File

@@ -9,10 +9,34 @@ package config
import (
"fmt"
"sort"
"github.com/syncthing/syncthing/lib/protocol"
)
const defaultNumConnections = 1 // number of connections to use by default; may change in the future.
type DeviceConfiguration struct {
DeviceID protocol.DeviceID `json:"deviceID" xml:"id,attr" nodefault:"true"`
Name string `json:"name" xml:"name,attr,omitempty"`
Addresses []string `json:"addresses" xml:"address,omitempty"`
Compression Compression `json:"compression" xml:"compression,attr"`
CertName string `json:"certName" xml:"certName,attr,omitempty"`
Introducer bool `json:"introducer" xml:"introducer,attr"`
SkipIntroductionRemovals bool `json:"skipIntroductionRemovals" xml:"skipIntroductionRemovals,attr"`
IntroducedBy protocol.DeviceID `json:"introducedBy" xml:"introducedBy,attr" nodefault:"true"`
Paused bool `json:"paused" xml:"paused"`
AllowedNetworks []string `json:"allowedNetworks" xml:"allowedNetwork,omitempty"`
AutoAcceptFolders bool `json:"autoAcceptFolders" xml:"autoAcceptFolders"`
MaxSendKbps int `json:"maxSendKbps" xml:"maxSendKbps"`
MaxRecvKbps int `json:"maxRecvKbps" xml:"maxRecvKbps"`
IgnoredFolders []ObservedFolder `json:"ignoredFolders" xml:"ignoredFolder"`
DeprecatedPendingFolders []ObservedFolder `json:"-" xml:"pendingFolder,omitempty"` // Deprecated: Do not use.
MaxRequestKiB int `json:"maxRequestKiB" xml:"maxRequestKiB"`
Untrusted bool `json:"untrusted" xml:"untrusted"`
RemoteGUIPort int `json:"remoteGUIPort" xml:"remoteGUIPort"`
RawNumConnections int `json:"numConnections" xml:"numConnections"`
}
func (cfg DeviceConfiguration) Copy() DeviceConfiguration {
c := cfg
c.Addresses = make([]string, len(cfg.Addresses))

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2016 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package config
import "github.com/syncthing/syncthing/lib/fs"
type FilesystemType int32
const (
FilesystemTypeBasic FilesystemType = 0
FilesystemTypeFake FilesystemType = 1
)
func (t FilesystemType) String() string {
switch t {
case FilesystemTypeBasic:
return "basic"
case FilesystemTypeFake:
return "fake"
default:
return "unknown"
}
}
func (t FilesystemType) ToFS() fs.FilesystemType {
switch t {
case FilesystemTypeBasic:
return fs.FilesystemTypeBasic
case FilesystemTypeFake:
return fs.FilesystemTypeFake
default:
return fs.FilesystemTypeBasic
}
}
func (t FilesystemType) MarshalText() ([]byte, error) {
return []byte(t.String()), nil
}
func (t *FilesystemType) UnmarshalText(bs []byte) error {
switch string(bs) {
case "basic":
*t = FilesystemTypeBasic
case "fake":
*t = FilesystemTypeFake
default:
*t = FilesystemTypeBasic
}
return nil
}

View File

@@ -33,11 +33,82 @@ var (
const (
DefaultMarkerName = ".stfolder"
EncryptionTokenName = "syncthing-encryption_password_token"
EncryptionTokenName = "syncthing-encryption_password_token" //nolint: gosec
maxConcurrentWritesDefault = 2
maxConcurrentWritesLimit = 64
)
type FolderDeviceConfiguration struct {
DeviceID protocol.DeviceID `json:"deviceID" xml:"id,attr"`
IntroducedBy protocol.DeviceID `json:"introducedBy" xml:"introducedBy,attr"`
EncryptionPassword string `json:"encryptionPassword" xml:"encryptionPassword"`
}
type FolderConfiguration struct {
ID string `json:"id" xml:"id,attr" nodefault:"true"`
Label string `json:"label" xml:"label,attr" restart:"false"`
FilesystemType FilesystemType `json:"filesystemType" xml:"filesystemType"`
Path string `json:"path" xml:"path,attr" default:"~"`
Type FolderType `json:"type" xml:"type,attr"`
Devices []FolderDeviceConfiguration `json:"devices" xml:"device"`
RescanIntervalS int `json:"rescanIntervalS" xml:"rescanIntervalS,attr" default:"3600"`
FSWatcherEnabled bool `json:"fsWatcherEnabled" xml:"fsWatcherEnabled,attr" default:"true"`
FSWatcherDelayS float64 `json:"fsWatcherDelayS" xml:"fsWatcherDelayS,attr" default:"10"`
FSWatcherTimeoutS float64 `json:"fsWatcherTimeoutS" xml:"fsWatcherTimeoutS,attr"`
IgnorePerms bool `json:"ignorePerms" xml:"ignorePerms,attr"`
AutoNormalize bool `json:"autoNormalize" xml:"autoNormalize,attr" default:"true"`
MinDiskFree Size `json:"minDiskFree" xml:"minDiskFree" default:"1 %"`
Versioning VersioningConfiguration `json:"versioning" xml:"versioning"`
Copiers int `json:"copiers" xml:"copiers"`
PullerMaxPendingKiB int `json:"pullerMaxPendingKiB" xml:"pullerMaxPendingKiB"`
Hashers int `json:"hashers" xml:"hashers"`
Order PullOrder `json:"order" xml:"order"`
IgnoreDelete bool `json:"ignoreDelete" xml:"ignoreDelete"`
ScanProgressIntervalS int `json:"scanProgressIntervalS" xml:"scanProgressIntervalS"`
PullerPauseS int `json:"pullerPauseS" xml:"pullerPauseS"`
MaxConflicts int `json:"maxConflicts" xml:"maxConflicts" default:"10"`
DisableSparseFiles bool `json:"disableSparseFiles" xml:"disableSparseFiles"`
DisableTempIndexes bool `json:"disableTempIndexes" xml:"disableTempIndexes"`
Paused bool `json:"paused" xml:"paused"`
WeakHashThresholdPct int `json:"weakHashThresholdPct" xml:"weakHashThresholdPct"`
MarkerName string `json:"markerName" xml:"markerName"`
CopyOwnershipFromParent bool `json:"copyOwnershipFromParent" xml:"copyOwnershipFromParent"`
RawModTimeWindowS int `json:"modTimeWindowS" xml:"modTimeWindowS"`
MaxConcurrentWrites int `json:"maxConcurrentWrites" xml:"maxConcurrentWrites" default:"2"`
DisableFsync bool `json:"disableFsync" xml:"disableFsync"`
BlockPullOrder BlockPullOrder `json:"blockPullOrder" xml:"blockPullOrder"`
CopyRangeMethod CopyRangeMethod `json:"copyRangeMethod" xml:"copyRangeMethod" default:"standard"`
CaseSensitiveFS bool `json:"caseSensitiveFS" xml:"caseSensitiveFS"`
JunctionsAsDirs bool `json:"junctionsAsDirs" xml:"junctionsAsDirs"`
SyncOwnership bool `json:"syncOwnership" xml:"syncOwnership"`
SendOwnership bool `json:"sendOwnership" xml:"sendOwnership"`
SyncXattrs bool `json:"syncXattrs" xml:"syncXattrs"`
SendXattrs bool `json:"sendXattrs" xml:"sendXattrs"`
XattrFilter XattrFilter `json:"xattrFilter" xml:"xattrFilter"`
// Legacy deprecated
DeprecatedReadOnly bool `json:"-" xml:"ro,attr,omitempty"` // Deprecated: Do not use.
DeprecatedMinDiskFreePct float64 `json:"-" xml:"minDiskFreePct,omitempty"` // Deprecated: Do not use.
DeprecatedPullers int `json:"-" xml:"pullers,omitempty"` // Deprecated: Do not use.
DeprecatedScanOwnership bool `json:"-" xml:"scanOwnership,omitempty"` // Deprecated: Do not use.
}
// 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.
type XattrFilter struct {
Entries []XattrFilterEntry `json:"entries" xml:"entry"`
MaxSingleEntrySize int `json:"maxSingleEntrySize" xml:"maxSingleEntrySize" default:"1024"`
MaxTotalSize int `json:"maxTotalSize" xml:"maxTotalSize" default:"4096"`
}
type XattrFilterEntry struct {
Match string `json:"match" xml:"match,attr"`
Permit bool `json:"permit" xml:"permit,attr"`
}
func (f FolderConfiguration) Copy() FolderConfiguration {
c := f
c.Devices = make([]FolderDeviceConfiguration, len(f.Devices))
@@ -53,7 +124,7 @@ func (f FolderConfiguration) Filesystem(fset *db.FileSet) fs.Filesystem {
// This is intentionally not a pointer method, because things like
// cfg.Folders["default"].Filesystem(nil) should be valid.
opts := make([]fs.Option, 0, 3)
if f.FilesystemType == fs.FilesystemTypeBasic && f.JunctionsAsDirs {
if f.FilesystemType == FilesystemTypeBasic && f.JunctionsAsDirs {
opts = append(opts, new(fs.OptionJunctionsAsDirs))
}
if !f.CaseSensitiveFS {
@@ -62,7 +133,7 @@ func (f FolderConfiguration) Filesystem(fset *db.FileSet) fs.Filesystem {
if fset != nil {
opts = append(opts, fset.MtimeOption())
}
return fs.NewFilesystem(f.FilesystemType, f.Path, opts...)
return fs.NewFilesystem(f.FilesystemType.ToFS(), f.Path, opts...)
}
func (f FolderConfiguration) ModTimeWindow() time.Duration {
@@ -300,7 +371,7 @@ func (f *FolderConfiguration) CheckAvailableSpace(req uint64) error {
fs := f.Filesystem(nil)
usage, err := fs.Usage(".")
if err != nil {
return nil
return nil //nolint: nilerr
}
if err := checkAvailableSpace(req, f.MinDiskFree, usage); err != nil {
return fmt.Errorf("insufficient space in folder %v (%v): %w", f.Description(), fs.URI(), err)

View File

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,15 @@
package config
type FolderType int32
const (
FolderTypeSendReceive FolderType = 0
FolderTypeSendOnly FolderType = 1
FolderTypeReceiveOnly FolderType = 2
FolderTypeReceiveEncrypted FolderType = 3
)
func (t FolderType) String() string {
switch t {
case FolderTypeSendReceive:

View File

@@ -1,77 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/foldertype.proto
package config
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type FolderType int32
const (
FolderTypeSendReceive FolderType = 0
FolderTypeSendOnly FolderType = 1
FolderTypeReceiveOnly FolderType = 2
FolderTypeReceiveEncrypted FolderType = 3
)
var FolderType_name = map[int32]string{
0: "FOLDER_TYPE_SEND_RECEIVE",
1: "FOLDER_TYPE_SEND_ONLY",
2: "FOLDER_TYPE_RECEIVE_ONLY",
3: "FOLDER_TYPE_RECEIVE_ENCRYPTED",
}
var FolderType_value = map[string]int32{
"FOLDER_TYPE_SEND_RECEIVE": 0,
"FOLDER_TYPE_SEND_ONLY": 1,
"FOLDER_TYPE_RECEIVE_ONLY": 2,
"FOLDER_TYPE_RECEIVE_ENCRYPTED": 3,
}
func (FolderType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_ea6ddb20c0633575, []int{0}
}
func init() {
proto.RegisterEnum("config.FolderType", FolderType_name, FolderType_value)
}
func init() { proto.RegisterFile("lib/config/foldertype.proto", fileDescriptor_ea6ddb20c0633575) }
var fileDescriptor_ea6ddb20c0633575 = []byte{
// 287 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xce, 0xc9, 0x4c, 0xd2,
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x4f, 0xcb, 0xcf, 0x49, 0x49, 0x2d, 0x2a, 0xa9, 0x2c,
0x48, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x48, 0x48, 0x29, 0x17, 0xa5, 0x16,
0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30,
0x0b, 0xa2, 0x58, 0xeb, 0x17, 0x23, 0x17, 0x97, 0x1b, 0xd8, 0x84, 0x90, 0xca, 0x82, 0x54, 0x21,
0x73, 0x2e, 0x09, 0x37, 0x7f, 0x1f, 0x17, 0xd7, 0xa0, 0xf8, 0x90, 0xc8, 0x00, 0xd7, 0xf8, 0x60,
0x57, 0x3f, 0x97, 0xf8, 0x20, 0x57, 0x67, 0x57, 0xcf, 0x30, 0x57, 0x01, 0x06, 0x29, 0xc9, 0xae,
0xb9, 0x0a, 0xa2, 0x08, 0xd5, 0xc1, 0xa9, 0x79, 0x29, 0x41, 0xa9, 0xc9, 0xa9, 0x99, 0x65, 0xa9,
0x42, 0x86, 0x5c, 0xa2, 0x18, 0x1a, 0xfd, 0xfd, 0x7c, 0x22, 0x05, 0x18, 0xa5, 0xc4, 0xba, 0xe6,
0x2a, 0x08, 0xa1, 0xea, 0xf2, 0xcf, 0xcb, 0xa9, 0x44, 0xb7, 0x0b, 0x6a, 0x0d, 0x44, 0x17, 0x13,
0xba, 0x5d, 0x50, 0x7b, 0xc0, 0x1a, 0x1d, 0xb9, 0x64, 0xb1, 0x69, 0x74, 0xf5, 0x73, 0x0e, 0x8a,
0x0c, 0x08, 0x71, 0x75, 0x11, 0x60, 0x96, 0x92, 0xeb, 0x9a, 0xab, 0x20, 0x85, 0xa1, 0xdb, 0x35,
0x2f, 0xb9, 0xa8, 0xb2, 0xa0, 0x24, 0x35, 0x45, 0x8a, 0x65, 0xc5, 0x12, 0x39, 0x06, 0x27, 0xef,
0x13, 0x0f, 0xe5, 0x18, 0x2e, 0x3c, 0x94, 0x63, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39,
0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x16, 0x3c, 0x96, 0x63, 0xbc, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63,
0x39, 0x86, 0x28, 0xcd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xe2,
0xca, 0xbc, 0xe4, 0x92, 0x8c, 0xcc, 0xbc, 0x74, 0x24, 0x16, 0x22, 0x1e, 0x92, 0xd8, 0xc0, 0x01,
0x6a, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x87, 0xbe, 0x2d, 0x9c, 0x01, 0x00, 0x00,
}

View File

@@ -18,6 +18,23 @@ import (
"github.com/syncthing/syncthing/lib/rand"
)
type GUIConfiguration struct {
Enabled bool `json:"enabled" xml:"enabled,attr" default:"true"`
RawAddress string `json:"address" xml:"address" default:"127.0.0.1:8384"`
RawUnixSocketPermissions string `json:"unixSocketPermissions" xml:"unixSocketPermissions,omitempty"`
User string `json:"user" xml:"user,omitempty"`
Password string `json:"password" xml:"password,omitempty"`
AuthMode AuthMode `json:"authMode" xml:"authMode,omitempty"`
RawUseTLS bool `json:"useTLS" xml:"tls,attr"`
APIKey string `json:"apiKey" xml:"apikey,omitempty"`
InsecureAdminAccess bool `json:"insecureAdminAccess" xml:"insecureAdminAccess,omitempty"`
Theme string `json:"theme" xml:"theme" default:"default"`
Debugging bool `json:"debugging" xml:"debugging,attr"`
InsecureSkipHostCheck bool `json:"insecureSkipHostcheck" xml:"insecureSkipHostcheck,omitempty"`
InsecureAllowFrameLoading bool `json:"insecureAllowFrameLoading" xml:"insecureAllowFrameLoading,omitempty"`
SendBasicAuthPrompt bool `json:"sendBasicAuthPrompt" xml:"sendBasicAuthPrompt,attr"`
}
func (c GUIConfiguration) IsAuthEnabled() bool {
// This function should match isAuthEnabled() in syncthingController.js
return c.AuthMode == AuthModeLDAP || (len(c.User) > 0 && len(c.Password) > 0)

View File

@@ -1,840 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/guiconfiguration.proto
package config
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
_ "github.com/syncthing/syncthing/proto/ext"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type GUIConfiguration struct {
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled" xml:"enabled,attr" default:"true"`
RawAddress string `protobuf:"bytes,2,opt,name=address,proto3" json:"address" xml:"address" default:"127.0.0.1:8384"`
RawUnixSocketPermissions string `protobuf:"bytes,3,opt,name=unix_socket_permissions,json=unixSocketPermissions,proto3" json:"unixSocketPermissions" xml:"unixSocketPermissions,omitempty"`
User string `protobuf:"bytes,4,opt,name=user,proto3" json:"user" xml:"user,omitempty"`
Password string `protobuf:"bytes,5,opt,name=password,proto3" json:"password" xml:"password,omitempty"`
AuthMode AuthMode `protobuf:"varint,6,opt,name=auth_mode,json=authMode,proto3,enum=config.AuthMode" json:"authMode" xml:"authMode,omitempty"`
RawUseTLS bool `protobuf:"varint,7,opt,name=use_tls,json=useTls,proto3" json:"useTLS" xml:"tls,attr"`
APIKey string `protobuf:"bytes,8,opt,name=api_key,json=apiKey,proto3" json:"apiKey" xml:"apikey,omitempty"`
InsecureAdminAccess bool `protobuf:"varint,9,opt,name=insecure_admin_access,json=insecureAdminAccess,proto3" json:"insecureAdminAccess" xml:"insecureAdminAccess,omitempty"`
Theme string `protobuf:"bytes,10,opt,name=theme,proto3" json:"theme" xml:"theme" default:"default"`
Debugging bool `protobuf:"varint,11,opt,name=debugging,proto3" json:"debugging" xml:"debugging,attr"`
InsecureSkipHostCheck bool `protobuf:"varint,12,opt,name=insecure_skip_host_check,json=insecureSkipHostCheck,proto3" json:"insecureSkipHostcheck" xml:"insecureSkipHostcheck,omitempty"`
InsecureAllowFrameLoading bool `protobuf:"varint,13,opt,name=insecure_allow_frame_loading,json=insecureAllowFrameLoading,proto3" json:"insecureAllowFrameLoading" xml:"insecureAllowFrameLoading,omitempty"`
SendBasicAuthPrompt bool `protobuf:"varint,14,opt,name=send_basic_auth_prompt,json=sendBasicAuthPrompt,proto3" json:"sendBasicAuthPrompt" xml:"sendBasicAuthPrompt,attr"`
}
func (m *GUIConfiguration) Reset() { *m = GUIConfiguration{} }
func (m *GUIConfiguration) String() string { return proto.CompactTextString(m) }
func (*GUIConfiguration) ProtoMessage() {}
func (*GUIConfiguration) Descriptor() ([]byte, []int) {
return fileDescriptor_2a9586d611855d64, []int{0}
}
func (m *GUIConfiguration) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *GUIConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_GUIConfiguration.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *GUIConfiguration) XXX_Merge(src proto.Message) {
xxx_messageInfo_GUIConfiguration.Merge(m, src)
}
func (m *GUIConfiguration) XXX_Size() int {
return m.ProtoSize()
}
func (m *GUIConfiguration) XXX_DiscardUnknown() {
xxx_messageInfo_GUIConfiguration.DiscardUnknown(m)
}
var xxx_messageInfo_GUIConfiguration proto.InternalMessageInfo
func init() {
proto.RegisterType((*GUIConfiguration)(nil), "config.GUIConfiguration")
}
func init() { proto.RegisterFile("lib/config/guiconfiguration.proto", fileDescriptor_2a9586d611855d64) }
var fileDescriptor_2a9586d611855d64 = []byte{
// 888 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0xcd, 0x6e, 0xdb, 0x46,
0x10, 0x16, 0x5b, 0x47, 0xb2, 0xb6, 0x89, 0x60, 0xb0, 0x4d, 0xca, 0x04, 0x0d, 0xd7, 0x51, 0xd8,
0xc2, 0x01, 0x02, 0x39, 0x71, 0x5a, 0x24, 0xf0, 0xa1, 0x80, 0x1c, 0x20, 0x4d, 0x60, 0x17, 0x30,
0xe8, 0xfa, 0x92, 0x0b, 0xb1, 0x22, 0xd7, 0xd2, 0x42, 0xfc, 0x2b, 0x77, 0x09, 0x5b, 0x87, 0xf6,
0x01, 0x7a, 0x2a, 0xdc, 0x73, 0x81, 0x3e, 0x43, 0x2f, 0x7d, 0x85, 0xdc, 0xa4, 0x53, 0xd1, 0xd3,
0x02, 0x91, 0xd1, 0x0b, 0x8f, 0x3c, 0xe6, 0x54, 0xec, 0xf2, 0x47, 0xa2, 0x4c, 0x37, 0xb9, 0xed,
0x7c, 0xf3, 0xcd, 0x7c, 0x33, 0xc3, 0x19, 0x10, 0xdc, 0x73, 0xc9, 0x60, 0xdb, 0x0e, 0xfc, 0x13,
0x32, 0xdc, 0x1e, 0xc6, 0x24, 0x7b, 0xc5, 0x11, 0x62, 0x24, 0xf0, 0x7b, 0x61, 0x14, 0xb0, 0x40,
0x6d, 0x66, 0xe0, 0x9d, 0xdb, 0x4b, 0x54, 0x14, 0xb3, 0x91, 0x17, 0x38, 0x38, 0xa3, 0xdc, 0x69,
0xe3, 0x33, 0x96, 0x3d, 0xbb, 0xff, 0xde, 0x00, 0x1b, 0xdf, 0x1d, 0xbf, 0x7a, 0xbe, 0x9c, 0x48,
0x1d, 0x80, 0x16, 0xf6, 0xd1, 0xc0, 0xc5, 0x8e, 0xa6, 0x6c, 0x2a, 0x5b, 0xeb, 0x7b, 0x2f, 0x13,
0x0e, 0x0b, 0x28, 0xe5, 0xf0, 0xde, 0x99, 0xe7, 0xee, 0x76, 0x73, 0xfb, 0x21, 0x62, 0x2c, 0xea,
0x6e, 0x3a, 0xf8, 0x04, 0xc5, 0x2e, 0xdb, 0xed, 0xb2, 0x28, 0xc6, 0xdd, 0x64, 0x6a, 0x5c, 0x5f,
0xf6, 0xbf, 0x9b, 0x1a, 0x6b, 0xc2, 0x61, 0x16, 0x59, 0xd4, 0x9f, 0x40, 0x0b, 0x39, 0x4e, 0x84,
0x29, 0xd5, 0x3e, 0xda, 0x54, 0xb6, 0xda, 0x7b, 0xf6, 0x9c, 0x43, 0x60, 0xa2, 0xd3, 0x7e, 0x86,
0x0a, 0xc5, 0x9c, 0x90, 0x72, 0xf8, 0x95, 0x54, 0xcc, 0xed, 0x25, 0xb1, 0xc7, 0x3b, 0x4f, 0x7b,
0x8f, 0x7a, 0x8f, 0x7a, 0x8f, 0x77, 0x9f, 0x3d, 0x79, 0xf6, 0x75, 0xf7, 0xdd, 0xd4, 0xe8, 0x54,
0xa1, 0xf3, 0x99, 0xb1, 0x94, 0xd4, 0x2c, 0x52, 0xaa, 0x7f, 0x2b, 0xe0, 0xf3, 0xd8, 0x27, 0x67,
0x16, 0x0d, 0xec, 0x31, 0x66, 0x56, 0x88, 0x23, 0x8f, 0x50, 0x4a, 0x02, 0x9f, 0x6a, 0x1f, 0xcb,
0x7a, 0x7e, 0x57, 0xe6, 0x1c, 0x6a, 0x26, 0x3a, 0x3d, 0xf6, 0xc9, 0xd9, 0x91, 0x64, 0x1d, 0x2e,
0x48, 0x09, 0x87, 0x37, 0xe3, 0x3a, 0x47, 0xca, 0xe1, 0x97, 0xb2, 0xd8, 0x5a, 0xef, 0xc3, 0xc0,
0x23, 0x0c, 0x7b, 0x21, 0x9b, 0x88, 0x11, 0xc1, 0xf7, 0x70, 0xce, 0x67, 0xc6, 0x95, 0x05, 0x98,
0xf5, 0xf2, 0xea, 0x0b, 0xb0, 0x16, 0x53, 0x1c, 0x69, 0x6b, 0xb2, 0x89, 0x9d, 0x84, 0x43, 0x69,
0xa7, 0x1c, 0x7e, 0x96, 0x95, 0x45, 0x71, 0x54, 0xad, 0xa2, 0x53, 0x85, 0x4c, 0xc9, 0x57, 0x5f,
0x83, 0xf5, 0x10, 0x51, 0x7a, 0x1a, 0x44, 0x8e, 0x76, 0x4d, 0xe6, 0xfa, 0x36, 0xe1, 0xb0, 0xc4,
0x52, 0x0e, 0x35, 0x99, 0xaf, 0x00, 0xaa, 0x39, 0xd5, 0xcb, 0xb0, 0x59, 0xc6, 0xaa, 0x1e, 0x68,
0x8b, 0x8d, 0xb4, 0xc4, 0x4a, 0x6a, 0xcd, 0x4d, 0x65, 0xab, 0xb3, 0xb3, 0xd1, 0xcb, 0x56, 0xb5,
0xd7, 0x8f, 0xd9, 0xe8, 0xfb, 0xc0, 0xc1, 0x99, 0x1c, 0xca, 0xad, 0x52, 0xae, 0x00, 0x56, 0xe4,
0x2e, 0xc3, 0x66, 0x19, 0xab, 0x62, 0xd0, 0x8a, 0x29, 0xb6, 0x98, 0x4b, 0xb5, 0x96, 0x5c, 0xe7,
0x83, 0x39, 0x87, 0x6d, 0x31, 0x58, 0x8a, 0x7f, 0x38, 0x38, 0x4a, 0x38, 0x6c, 0xc6, 0xf2, 0x95,
0x72, 0xd8, 0x91, 0x2a, 0xcc, 0xa5, 0xd9, 0x5a, 0x27, 0x53, 0x63, 0xbd, 0x30, 0xd2, 0xa9, 0x91,
0xf3, 0xce, 0x67, 0xc6, 0x22, 0xdc, 0x94, 0xa0, 0x4b, 0x85, 0x0c, 0x0a, 0x89, 0x35, 0xc6, 0x13,
0x6d, 0x5d, 0x0e, 0x4c, 0xc8, 0x34, 0xfb, 0x87, 0xaf, 0xf6, 0xf1, 0x44, 0x68, 0xa0, 0x90, 0xec,
0xe3, 0x49, 0xca, 0xe1, 0xad, 0xac, 0x93, 0x90, 0x8c, 0xf1, 0xa4, 0xda, 0xc7, 0xc6, 0x2a, 0x78,
0x3e, 0x33, 0xf2, 0x0c, 0x66, 0x1e, 0xaf, 0xfe, 0xa6, 0x80, 0x9b, 0xc4, 0xa7, 0xd8, 0x8e, 0x23,
0x6c, 0x21, 0xc7, 0x23, 0xbe, 0x85, 0x6c, 0x5b, 0xdc, 0x51, 0x5b, 0x36, 0x67, 0x25, 0x1c, 0x7e,
0x5a, 0x10, 0xfa, 0xc2, 0xdf, 0x97, 0xee, 0x94, 0xc3, 0xfb, 0x52, 0xb8, 0xc6, 0x57, 0xad, 0xe2,
0xee, 0xff, 0x32, 0xcc, 0xba, 0xe4, 0xea, 0x3e, 0xb8, 0xc6, 0x46, 0xd8, 0xc3, 0x1a, 0x90, 0xad,
0x7f, 0x93, 0x70, 0x98, 0x01, 0x29, 0x87, 0x77, 0xb3, 0x99, 0x0a, 0x6b, 0xe9, 0x74, 0xf3, 0x87,
0xb8, 0xd9, 0x56, 0xfe, 0x36, 0xb3, 0x10, 0xf5, 0x18, 0xb4, 0x1d, 0x3c, 0x88, 0x87, 0x43, 0xe2,
0x0f, 0xb5, 0x4f, 0x64, 0x57, 0x4f, 0x13, 0x0e, 0x17, 0x60, 0xb9, 0xcd, 0x25, 0x52, 0x7e, 0xae,
0x4e, 0x15, 0x32, 0x17, 0x41, 0xea, 0x5f, 0x0a, 0xd0, 0xca, 0xc9, 0xd1, 0x31, 0x09, 0xad, 0x51,
0x40, 0x99, 0x65, 0x8f, 0xb0, 0x3d, 0xd6, 0xae, 0x4b, 0x99, 0x9f, 0xc5, 0x5d, 0x17, 0x9c, 0xa3,
0x31, 0x09, 0x5f, 0x06, 0x94, 0x49, 0x42, 0x79, 0xd7, 0xb5, 0xde, 0x95, 0xbb, 0x7e, 0x0f, 0x27,
0x9d, 0x1a, 0xf5, 0x22, 0xe6, 0x25, 0xf8, 0xb9, 0x80, 0xd5, 0x3f, 0x15, 0xf0, 0xc5, 0xe2, 0x9b,
0xbb, 0x6e, 0x70, 0x6a, 0x9d, 0x44, 0xc8, 0xc3, 0x96, 0x1b, 0x20, 0x47, 0x0c, 0xe9, 0x86, 0xac,
0xfe, 0xc7, 0x84, 0xc3, 0xdb, 0xe5, 0xd7, 0x11, 0xb4, 0x17, 0x82, 0x75, 0x90, 0x91, 0x52, 0x0e,
0x1f, 0x54, 0x17, 0x60, 0x95, 0x51, 0xed, 0xe2, 0xfe, 0x07, 0xf0, 0xcc, 0xab, 0xe5, 0xd4, 0x5f,
0x14, 0x70, 0x8b, 0x62, 0xdf, 0xb1, 0x06, 0x88, 0x12, 0xdb, 0x92, 0x17, 0x1f, 0x46, 0x81, 0x17,
0x32, 0xad, 0x23, 0xcb, 0x3d, 0x16, 0x9b, 0x2a, 0x18, 0x7b, 0x82, 0x20, 0x0e, 0xff, 0x50, 0xba,
0x53, 0x0e, 0x75, 0x59, 0x68, 0x8d, 0xaf, 0xfc, 0xce, 0xda, 0x55, 0x4e, 0xb3, 0x2e, 0xe5, 0xde,
0xfe, 0x9b, 0xb7, 0x7a, 0x63, 0xf6, 0x56, 0x6f, 0xbc, 0x99, 0xeb, 0xca, 0x6c, 0xae, 0x2b, 0xbf,
0x5e, 0xe8, 0x8d, 0x3f, 0x2e, 0x74, 0x65, 0x76, 0xa1, 0x37, 0xfe, 0xb9, 0xd0, 0x1b, 0xaf, 0x1f,
0x0c, 0x09, 0x1b, 0xc5, 0x83, 0x9e, 0x1d, 0x78, 0xdb, 0x74, 0xe2, 0xdb, 0x6c, 0x44, 0xfc, 0xe1,
0xd2, 0x6b, 0xf1, 0x3b, 0x1d, 0x34, 0xe5, 0xbf, 0xf3, 0xc9, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff,
0xfe, 0x19, 0xb2, 0x3c, 0x8e, 0x07, 0x00, 0x00,
}
func (m *GUIConfiguration) Marshal() (dAtA []byte, err error) {
size := m.ProtoSize()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *GUIConfiguration) MarshalTo(dAtA []byte) (int, error) {
size := m.ProtoSize()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *GUIConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.SendBasicAuthPrompt {
i--
if m.SendBasicAuthPrompt {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x70
}
if m.InsecureAllowFrameLoading {
i--
if m.InsecureAllowFrameLoading {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x68
}
if m.InsecureSkipHostCheck {
i--
if m.InsecureSkipHostCheck {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x60
}
if m.Debugging {
i--
if m.Debugging {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x58
}
if len(m.Theme) > 0 {
i -= len(m.Theme)
copy(dAtA[i:], m.Theme)
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.Theme)))
i--
dAtA[i] = 0x52
}
if m.InsecureAdminAccess {
i--
if m.InsecureAdminAccess {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x48
}
if len(m.APIKey) > 0 {
i -= len(m.APIKey)
copy(dAtA[i:], m.APIKey)
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.APIKey)))
i--
dAtA[i] = 0x42
}
if m.RawUseTLS {
i--
if m.RawUseTLS {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x38
}
if m.AuthMode != 0 {
i = encodeVarintGuiconfiguration(dAtA, i, uint64(m.AuthMode))
i--
dAtA[i] = 0x30
}
if len(m.Password) > 0 {
i -= len(m.Password)
copy(dAtA[i:], m.Password)
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.Password)))
i--
dAtA[i] = 0x2a
}
if len(m.User) > 0 {
i -= len(m.User)
copy(dAtA[i:], m.User)
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.User)))
i--
dAtA[i] = 0x22
}
if len(m.RawUnixSocketPermissions) > 0 {
i -= len(m.RawUnixSocketPermissions)
copy(dAtA[i:], m.RawUnixSocketPermissions)
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.RawUnixSocketPermissions)))
i--
dAtA[i] = 0x1a
}
if len(m.RawAddress) > 0 {
i -= len(m.RawAddress)
copy(dAtA[i:], m.RawAddress)
i = encodeVarintGuiconfiguration(dAtA, i, uint64(len(m.RawAddress)))
i--
dAtA[i] = 0x12
}
if m.Enabled {
i--
if m.Enabled {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func encodeVarintGuiconfiguration(dAtA []byte, offset int, v uint64) int {
offset -= sovGuiconfiguration(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *GUIConfiguration) ProtoSize() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Enabled {
n += 2
}
l = len(m.RawAddress)
if l > 0 {
n += 1 + l + sovGuiconfiguration(uint64(l))
}
l = len(m.RawUnixSocketPermissions)
if l > 0 {
n += 1 + l + sovGuiconfiguration(uint64(l))
}
l = len(m.User)
if l > 0 {
n += 1 + l + sovGuiconfiguration(uint64(l))
}
l = len(m.Password)
if l > 0 {
n += 1 + l + sovGuiconfiguration(uint64(l))
}
if m.AuthMode != 0 {
n += 1 + sovGuiconfiguration(uint64(m.AuthMode))
}
if m.RawUseTLS {
n += 2
}
l = len(m.APIKey)
if l > 0 {
n += 1 + l + sovGuiconfiguration(uint64(l))
}
if m.InsecureAdminAccess {
n += 2
}
l = len(m.Theme)
if l > 0 {
n += 1 + l + sovGuiconfiguration(uint64(l))
}
if m.Debugging {
n += 2
}
if m.InsecureSkipHostCheck {
n += 2
}
if m.InsecureAllowFrameLoading {
n += 2
}
if m.SendBasicAuthPrompt {
n += 2
}
return n
}
func sovGuiconfiguration(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozGuiconfiguration(x uint64) (n int) {
return sovGuiconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *GUIConfiguration) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: GUIConfiguration: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: GUIConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Enabled", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Enabled = bool(v != 0)
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field RawAddress", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGuiconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGuiconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.RawAddress = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field RawUnixSocketPermissions", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGuiconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGuiconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.RawUnixSocketPermissions = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field User", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGuiconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGuiconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.User = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGuiconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGuiconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Password = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AuthMode", wireType)
}
m.AuthMode = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.AuthMode |= AuthMode(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 7:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field RawUseTLS", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.RawUseTLS = bool(v != 0)
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field APIKey", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGuiconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGuiconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.APIKey = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field InsecureAdminAccess", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.InsecureAdminAccess = bool(v != 0)
case 10:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Theme", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGuiconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGuiconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Theme = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 11:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Debugging", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Debugging = bool(v != 0)
case 12:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field InsecureSkipHostCheck", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.InsecureSkipHostCheck = bool(v != 0)
case 13:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field InsecureAllowFrameLoading", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.InsecureAllowFrameLoading = bool(v != 0)
case 14:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field SendBasicAuthPrompt", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.SendBasicAuthPrompt = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipGuiconfiguration(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGuiconfiguration
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGuiconfiguration(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGuiconfiguration
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthGuiconfiguration
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupGuiconfiguration
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthGuiconfiguration
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthGuiconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGuiconfiguration = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupGuiconfiguration = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -6,6 +6,15 @@
package config
type LDAPConfiguration struct {
Address string `json:"address" xml:"address,omitempty"`
BindDN string `json:"bindDN" xml:"bindDN,omitempty"`
Transport LDAPTransport `json:"transport" xml:"transport,omitempty"`
InsecureSkipVerify bool `json:"insecureSkipVerify" xml:"insecureSkipVerify,omitempty" default:"false"`
SearchBaseDN string `json:"searchBaseDN" xml:"searchBaseDN,omitempty"`
SearchFilter string `json:"searchFilter" xml:"searchFilter,omitempty"`
}
func (c LDAPConfiguration) Copy() LDAPConfiguration {
return c
}

View File

@@ -1,526 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/ldapconfiguration.proto
package config
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
_ "github.com/syncthing/syncthing/proto/ext"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type LDAPConfiguration struct {
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address" xml:"address,omitempty"`
BindDN string `protobuf:"bytes,2,opt,name=bind_dn,json=bindDn,proto3" json:"bindDN" xml:"bindDN,omitempty"`
Transport LDAPTransport `protobuf:"varint,3,opt,name=transport,proto3,enum=config.LDAPTransport" json:"transport" xml:"transport,omitempty"`
InsecureSkipVerify bool `protobuf:"varint,4,opt,name=insecure_skip_verify,json=insecureSkipVerify,proto3" json:"insecureSkipVerify" xml:"insecureSkipVerify,omitempty" default:"false"`
SearchBaseDN string `protobuf:"bytes,5,opt,name=search_base_dn,json=searchBaseDn,proto3" json:"searchBaseDN" xml:"searchBaseDN,omitempty"`
SearchFilter string `protobuf:"bytes,6,opt,name=search_filter,json=searchFilter,proto3" json:"searchFilter" xml:"searchFilter,omitempty"`
}
func (m *LDAPConfiguration) Reset() { *m = LDAPConfiguration{} }
func (m *LDAPConfiguration) String() string { return proto.CompactTextString(m) }
func (*LDAPConfiguration) ProtoMessage() {}
func (*LDAPConfiguration) Descriptor() ([]byte, []int) {
return fileDescriptor_9681ad7e41c73956, []int{0}
}
func (m *LDAPConfiguration) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *LDAPConfiguration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_LDAPConfiguration.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *LDAPConfiguration) XXX_Merge(src proto.Message) {
xxx_messageInfo_LDAPConfiguration.Merge(m, src)
}
func (m *LDAPConfiguration) XXX_Size() int {
return m.ProtoSize()
}
func (m *LDAPConfiguration) XXX_DiscardUnknown() {
xxx_messageInfo_LDAPConfiguration.DiscardUnknown(m)
}
var xxx_messageInfo_LDAPConfiguration proto.InternalMessageInfo
func init() {
proto.RegisterType((*LDAPConfiguration)(nil), "config.LDAPConfiguration")
}
func init() {
proto.RegisterFile("lib/config/ldapconfiguration.proto", fileDescriptor_9681ad7e41c73956)
}
var fileDescriptor_9681ad7e41c73956 = []byte{
// 500 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xbf, 0x6f, 0xd3, 0x40,
0x14, 0xb6, 0x81, 0xba, 0xc4, 0x2a, 0x15, 0x35, 0x50, 0x4c, 0x55, 0xf9, 0x22, 0xcb, 0x43, 0x90,
0x50, 0x22, 0x95, 0xad, 0x4c, 0x35, 0x15, 0x03, 0x20, 0x84, 0x5c, 0xe8, 0xc0, 0x12, 0xf9, 0xc7,
0x39, 0x39, 0xd5, 0x39, 0x5b, 0x77, 0xe7, 0xaa, 0xe1, 0xaf, 0x80, 0xfe, 0x05, 0xdd, 0xf8, 0x57,
0xba, 0xc5, 0x23, 0xd3, 0x49, 0x4d, 0x36, 0x8f, 0x1e, 0x99, 0x50, 0xce, 0x4e, 0x63, 0xa7, 0x51,
0xb7, 0xf7, 0xbe, 0xef, 0xbd, 0xef, 0x7d, 0x77, 0x4f, 0x4f, 0x35, 0x23, 0xe4, 0xf5, 0xfc, 0x18,
0x87, 0x68, 0xd0, 0x8b, 0x02, 0x37, 0x29, 0xc3, 0x94, 0xb8, 0x0c, 0xc5, 0xb8, 0x9b, 0x90, 0x98,
0xc5, 0x9a, 0x52, 0x82, 0x7b, 0xc6, 0x4a, 0x2d, 0x23, 0x2e, 0xa6, 0x49, 0x4c, 0x58, 0x59, 0xb7,
0xd7, 0x82, 0x17, 0x55, 0x68, 0xfe, 0x56, 0xd4, 0x9d, 0xcf, 0xc7, 0x47, 0x5f, 0xdf, 0xd7, 0xe5,
0xb4, 0xef, 0xea, 0xa6, 0x1b, 0x04, 0x04, 0x52, 0xaa, 0xcb, 0x6d, 0xb9, 0xd3, 0xb2, 0xdf, 0xe5,
0x1c, 0x2c, 0xa0, 0x82, 0x83, 0x97, 0x17, 0xa3, 0xe8, 0xd0, 0xac, 0xf2, 0x37, 0xf1, 0x08, 0x31,
0x38, 0x4a, 0xd8, 0xd8, 0xcc, 0x27, 0xd6, 0xce, 0x1d, 0xd4, 0x59, 0x34, 0x6a, 0xb1, 0xba, 0xe9,
0x21, 0x1c, 0xf4, 0x03, 0xac, 0x3f, 0x10, 0xb2, 0xa7, 0x53, 0x0e, 0x14, 0x1b, 0xe1, 0xe0, 0xf8,
0x4b, 0xce, 0x81, 0xe2, 0x89, 0xa8, 0xe0, 0x60, 0x57, 0xe8, 0x97, 0x69, 0x53, 0xfe, 0xe9, 0x2a,
0x58, 0x4c, 0xac, 0xaa, 0xef, 0x32, 0xb3, 0x2a, 0x2d, 0xa7, 0x44, 0xb0, 0x76, 0xae, 0xb6, 0x6e,
0xdf, 0xae, 0x3f, 0x6c, 0xcb, 0x9d, 0xed, 0x83, 0x17, 0xdd, 0xf2, 0x63, 0xba, 0xf3, 0x57, 0x7f,
0x5b, 0x90, 0xf6, 0x51, 0xce, 0xc1, 0xb2, 0xb6, 0xe0, 0xe0, 0x95, 0xb0, 0x70, 0x8b, 0x34, 0x5d,
0x3c, 0x5b, 0x83, 0x3b, 0xcb, 0x76, 0xed, 0x8f, 0xac, 0x3e, 0x47, 0x98, 0x42, 0x3f, 0x25, 0xb0,
0x4f, 0xcf, 0x50, 0xd2, 0x3f, 0x87, 0x04, 0x85, 0x63, 0xfd, 0x51, 0x5b, 0xee, 0x3c, 0xb6, 0xd3,
0x9c, 0x03, 0x6d, 0xc1, 0x9f, 0x9c, 0xa1, 0xe4, 0x54, 0xb0, 0x05, 0x07, 0x07, 0x62, 0xea, 0x5d,
0xaa, 0x36, 0xbe, 0x1d, 0xc0, 0xd0, 0x4d, 0x23, 0x76, 0x68, 0x86, 0x6e, 0x44, 0xe1, 0xdc, 0xce,
0xfe, 0x7d, 0x0d, 0xff, 0x26, 0xd6, 0x86, 0xa8, 0x74, 0xd6, 0x8c, 0xd4, 0xae, 0x64, 0x75, 0x9b,
0x42, 0x97, 0xf8, 0xc3, 0xbe, 0xe7, 0x52, 0x38, 0x5f, 0xcd, 0x86, 0x58, 0xcd, 0xcf, 0x29, 0x07,
0x5b, 0x27, 0x82, 0xb1, 0x5d, 0x0a, 0xc5, 0x82, 0xb6, 0x68, 0x2d, 0x2f, 0x38, 0xd8, 0x17, 0x6e,
0xeb, 0x60, 0xf3, 0x9b, 0x76, 0xd7, 0x53, 0xc5, 0xc4, 0x6a, 0x28, 0x5d, 0x66, 0x56, 0x63, 0x92,
0x53, 0x67, 0xb1, 0x16, 0xab, 0x4f, 0x2a, 0x87, 0x21, 0x8a, 0x18, 0x24, 0xba, 0x22, 0x0c, 0x7e,
0x5c, 0x1a, 0xfa, 0x20, 0xf0, 0x15, 0x43, 0x25, 0xb8, 0xd6, 0xd0, 0x2a, 0xe5, 0x34, 0x74, 0xec,
0x4f, 0xd7, 0x37, 0x86, 0x94, 0xdd, 0x18, 0xd2, 0xf5, 0xd4, 0x90, 0xb3, 0xa9, 0x21, 0xff, 0x9a,
0x19, 0xd2, 0xd5, 0xcc, 0x90, 0xb3, 0x99, 0x21, 0xfd, 0x9d, 0x19, 0xd2, 0x8f, 0xd7, 0x03, 0xc4,
0x86, 0xa9, 0xd7, 0xf5, 0xe3, 0x51, 0x8f, 0x8e, 0xb1, 0xcf, 0x86, 0x08, 0x0f, 0x6a, 0xd1, 0xf2,
0xfe, 0x3c, 0x45, 0xdc, 0xd9, 0xdb, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x64, 0x4b, 0x05,
0xc0, 0x03, 0x00, 0x00,
}
func (m *LDAPConfiguration) Marshal() (dAtA []byte, err error) {
size := m.ProtoSize()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *LDAPConfiguration) MarshalTo(dAtA []byte) (int, error) {
size := m.ProtoSize()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *LDAPConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.SearchFilter) > 0 {
i -= len(m.SearchFilter)
copy(dAtA[i:], m.SearchFilter)
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.SearchFilter)))
i--
dAtA[i] = 0x32
}
if len(m.SearchBaseDN) > 0 {
i -= len(m.SearchBaseDN)
copy(dAtA[i:], m.SearchBaseDN)
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.SearchBaseDN)))
i--
dAtA[i] = 0x2a
}
if m.InsecureSkipVerify {
i--
if m.InsecureSkipVerify {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x20
}
if m.Transport != 0 {
i = encodeVarintLdapconfiguration(dAtA, i, uint64(m.Transport))
i--
dAtA[i] = 0x18
}
if len(m.BindDN) > 0 {
i -= len(m.BindDN)
copy(dAtA[i:], m.BindDN)
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.BindDN)))
i--
dAtA[i] = 0x12
}
if len(m.Address) > 0 {
i -= len(m.Address)
copy(dAtA[i:], m.Address)
i = encodeVarintLdapconfiguration(dAtA, i, uint64(len(m.Address)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintLdapconfiguration(dAtA []byte, offset int, v uint64) int {
offset -= sovLdapconfiguration(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *LDAPConfiguration) ProtoSize() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Address)
if l > 0 {
n += 1 + l + sovLdapconfiguration(uint64(l))
}
l = len(m.BindDN)
if l > 0 {
n += 1 + l + sovLdapconfiguration(uint64(l))
}
if m.Transport != 0 {
n += 1 + sovLdapconfiguration(uint64(m.Transport))
}
if m.InsecureSkipVerify {
n += 2
}
l = len(m.SearchBaseDN)
if l > 0 {
n += 1 + l + sovLdapconfiguration(uint64(l))
}
l = len(m.SearchFilter)
if l > 0 {
n += 1 + l + sovLdapconfiguration(uint64(l))
}
return n
}
func sovLdapconfiguration(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozLdapconfiguration(x uint64) (n int) {
return sovLdapconfiguration(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *LDAPConfiguration) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: LDAPConfiguration: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: LDAPConfiguration: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthLdapconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthLdapconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Address = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field BindDN", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthLdapconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthLdapconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.BindDN = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Transport", wireType)
}
m.Transport = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Transport |= LDAPTransport(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field InsecureSkipVerify", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.InsecureSkipVerify = bool(v != 0)
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SearchBaseDN", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthLdapconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthLdapconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SearchBaseDN = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SearchFilter", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthLdapconfiguration
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthLdapconfiguration
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SearchFilter = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipLdapconfiguration(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthLdapconfiguration
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipLdapconfiguration(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowLdapconfiguration
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthLdapconfiguration
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupLdapconfiguration
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthLdapconfiguration
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthLdapconfiguration = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowLdapconfiguration = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupLdapconfiguration = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -6,6 +6,14 @@
package config
type LDAPTransport int32
const (
LDAPTransportPlain LDAPTransport = 0
LDAPTransportTLS LDAPTransport = 2
LDAPTransportStartTLS LDAPTransport = 3
)
func (t LDAPTransport) String() string {
switch t {
case LDAPTransportPlain:

View File

@@ -1,75 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/ldaptransport.proto
package config
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
_ "github.com/syncthing/syncthing/proto/ext"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type LDAPTransport int32
const (
LDAPTransportPlain LDAPTransport = 0
LDAPTransportTLS LDAPTransport = 2
LDAPTransportStartTLS LDAPTransport = 3
)
var LDAPTransport_name = map[int32]string{
0: "LDAP_TRANSPORT_PLAIN",
2: "LDAP_TRANSPORT_TLS",
3: "LDAP_TRANSPORT_START_TLS",
}
var LDAPTransport_value = map[string]int32{
"LDAP_TRANSPORT_PLAIN": 0,
"LDAP_TRANSPORT_TLS": 2,
"LDAP_TRANSPORT_START_TLS": 3,
}
func (LDAPTransport) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_79795fc8505b82bf, []int{0}
}
func init() {
proto.RegisterEnum("config.LDAPTransport", LDAPTransport_name, LDAPTransport_value)
}
func init() { proto.RegisterFile("lib/config/ldaptransport.proto", fileDescriptor_79795fc8505b82bf) }
var fileDescriptor_79795fc8505b82bf = []byte{
// 273 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcb, 0xc9, 0x4c, 0xd2,
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0xcf, 0x49, 0x49, 0x2c, 0x28, 0x29, 0x4a, 0xcc, 0x2b,
0x2e, 0xc8, 0x2f, 0x2a, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0xc8, 0x49, 0x29,
0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93, 0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3,
0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0x8a, 0x33, 0xb5, 0x02, 0xaa, 0x4f, 0xeb, 0x23, 0x23, 0x17,
0xaf, 0x8f, 0x8b, 0x63, 0x40, 0x08, 0xcc, 0x3c, 0x21, 0x37, 0x2e, 0x11, 0x90, 0x40, 0x7c, 0x48,
0x90, 0xa3, 0x5f, 0x70, 0x80, 0x7f, 0x50, 0x48, 0x7c, 0x80, 0x8f, 0xa3, 0xa7, 0x9f, 0x00, 0x83,
0x94, 0x4e, 0xd7, 0x5c, 0x05, 0x21, 0x14, 0xc5, 0x01, 0x39, 0x89, 0x99, 0x79, 0x97, 0xfa, 0x54,
0xb1, 0x88, 0x0a, 0x39, 0x70, 0x09, 0xa1, 0x99, 0x13, 0xe2, 0x13, 0x2c, 0xc0, 0x24, 0xa5, 0xd1,
0x35, 0x57, 0x41, 0x00, 0x45, 0x7d, 0x88, 0x4f, 0xf0, 0xa5, 0x3e, 0x55, 0x0c, 0x31, 0xa1, 0x00,
0x2e, 0x09, 0x34, 0x13, 0x82, 0x43, 0x1c, 0xa1, 0xe6, 0x30, 0x4b, 0x19, 0x75, 0xcd, 0x55, 0x10,
0x45, 0xd1, 0x13, 0x5c, 0x92, 0x08, 0x33, 0x0c, 0xbb, 0x84, 0x14, 0xcb, 0x8a, 0x25, 0x72, 0x0c,
0x4e, 0xde, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85,
0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x2c, 0x78, 0x2c, 0xc7, 0x78, 0xe1, 0xb1, 0x1c, 0xc3,
0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x9a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9,
0xfa, 0xc5, 0x95, 0x79, 0xc9, 0x25, 0x19, 0x99, 0x79, 0xe9, 0x48, 0x2c, 0x44, 0x64, 0x24, 0xb1,
0x81, 0xc3, 0xd1, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x56, 0xde, 0x17, 0xa1, 0x01, 0x00,
0x00,
}

View File

@@ -114,7 +114,7 @@ func migrateToConfigV35(cfg *Configuration) {
for i, fcfg := range cfg.Folders {
params := fcfg.Versioning.Params
if params["fsType"] != "" {
var fsType fs.FilesystemType
var fsType FilesystemType
_ = fsType.UnmarshalText([]byte(params["fsType"]))
cfg.Folders[i].Versioning.FSType = fsType
}
@@ -228,7 +228,7 @@ func migrateToConfigV23(cfg *Configuration) {
func migrateToConfigV22(cfg *Configuration) {
for i := range cfg.Folders {
cfg.Folders[i].FilesystemType = fs.FilesystemTypeBasic
cfg.Folders[i].FilesystemType = FilesystemTypeBasic
// Migrate to templated external versioner commands
if cfg.Folders[i].Versioning.Type == "external" {
cfg.Folders[i].Versioning.Params["command"] += " %FOLDER_PATH% %FILE_PATH%"
@@ -238,7 +238,7 @@ func migrateToConfigV22(cfg *Configuration) {
func migrateToConfigV21(cfg *Configuration) {
for _, folder := range cfg.Folders {
if folder.FilesystemType != fs.FilesystemTypeBasic {
if folder.FilesystemType != FilesystemTypeBasic {
continue
}
switch folder.Versioning.Type {

26
lib/config/observed.go Normal file
View File

@@ -0,0 +1,26 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package config
import (
"time"
"github.com/syncthing/syncthing/lib/protocol"
)
type ObservedFolder struct {
Time time.Time `json:"time" xml:"time,attr"`
ID string `json:"id" xml:"id,attr"`
Label string `json:"label" xml:"label,attr"`
}
type ObservedDevice struct {
Time time.Time `json:"time" xml:"time,attr"`
ID protocol.DeviceID `json:"deviceID" xml:"id,attr"`
Name string `json:"name" xml:"name,attr"`
Address string `json:"address" xml:"address,attr"`
}

View File

@@ -1,716 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/observed.proto
package config
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
github_com_syncthing_syncthing_lib_protocol "github.com/syncthing/syncthing/lib/protocol"
_ "github.com/syncthing/syncthing/proto/ext"
_ "google.golang.org/protobuf/types/known/timestamppb"
io "io"
math "math"
math_bits "math/bits"
time "time"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
var _ = time.Kitchen
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type ObservedFolder struct {
Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time" xml:"time,attr"`
ID string `protobuf:"bytes,2,opt,name=id,proto3" json:"id" xml:"id,attr"`
Label string `protobuf:"bytes,3,opt,name=label,proto3" json:"label" xml:"label,attr"`
}
func (m *ObservedFolder) Reset() { *m = ObservedFolder{} }
func (m *ObservedFolder) String() string { return proto.CompactTextString(m) }
func (*ObservedFolder) ProtoMessage() {}
func (*ObservedFolder) Descriptor() ([]byte, []int) {
return fileDescriptor_49f68ff7b178722f, []int{0}
}
func (m *ObservedFolder) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ObservedFolder) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ObservedFolder.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ObservedFolder) XXX_Merge(src proto.Message) {
xxx_messageInfo_ObservedFolder.Merge(m, src)
}
func (m *ObservedFolder) XXX_Size() int {
return m.ProtoSize()
}
func (m *ObservedFolder) XXX_DiscardUnknown() {
xxx_messageInfo_ObservedFolder.DiscardUnknown(m)
}
var xxx_messageInfo_ObservedFolder proto.InternalMessageInfo
type ObservedDevice struct {
Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time" xml:"time,attr"`
ID github_com_syncthing_syncthing_lib_protocol.DeviceID `protobuf:"bytes,2,opt,name=id,proto3,customtype=github.com/syncthing/syncthing/lib/protocol.DeviceID" json:"deviceID" xml:"id,attr"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name" xml:"name,attr"`
Address string `protobuf:"bytes,4,opt,name=address,proto3" json:"address" xml:"address,attr"`
}
func (m *ObservedDevice) Reset() { *m = ObservedDevice{} }
func (m *ObservedDevice) String() string { return proto.CompactTextString(m) }
func (*ObservedDevice) ProtoMessage() {}
func (*ObservedDevice) Descriptor() ([]byte, []int) {
return fileDescriptor_49f68ff7b178722f, []int{1}
}
func (m *ObservedDevice) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ObservedDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ObservedDevice.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ObservedDevice) XXX_Merge(src proto.Message) {
xxx_messageInfo_ObservedDevice.Merge(m, src)
}
func (m *ObservedDevice) XXX_Size() int {
return m.ProtoSize()
}
func (m *ObservedDevice) XXX_DiscardUnknown() {
xxx_messageInfo_ObservedDevice.DiscardUnknown(m)
}
var xxx_messageInfo_ObservedDevice proto.InternalMessageInfo
func init() {
proto.RegisterType((*ObservedFolder)(nil), "config.ObservedFolder")
proto.RegisterType((*ObservedDevice)(nil), "config.ObservedDevice")
}
func init() { proto.RegisterFile("lib/config/observed.proto", fileDescriptor_49f68ff7b178722f) }
var fileDescriptor_49f68ff7b178722f = []byte{
// 440 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x93, 0x3f, 0x6f, 0xd4, 0x30,
0x00, 0xc5, 0xe3, 0xf4, 0x68, 0x39, 0x53, 0xfe, 0x28, 0xd3, 0x71, 0x83, 0x5d, 0x9d, 0x32, 0x1c,
0x02, 0x25, 0xfc, 0x9b, 0x10, 0x42, 0xe2, 0x74, 0x42, 0x3a, 0x75, 0x40, 0x8a, 0x98, 0x98, 0x48,
0x62, 0x37, 0xb5, 0x94, 0x9c, 0xab, 0xc4, 0xad, 0xca, 0xc6, 0xc8, 0xd8, 0xf2, 0x09, 0xf8, 0x38,
0xb7, 0x5d, 0x46, 0xc4, 0x60, 0xd4, 0xcb, 0x96, 0x31, 0x12, 0x3b, 0x8a, 0x9d, 0xf8, 0x6e, 0x42,
0x4c, 0x6c, 0x7e, 0x4f, 0xcf, 0x3f, 0xf9, 0xbd, 0x28, 0xf0, 0x61, 0xca, 0x22, 0x3f, 0xe6, 0xcb,
0x13, 0x96, 0xf8, 0x3c, 0x2a, 0x68, 0x7e, 0x41, 0x89, 0x77, 0x96, 0x73, 0xc1, 0x9d, 0x7d, 0x6d,
0x8f, 0x71, 0xc2, 0x79, 0x92, 0x52, 0x5f, 0xb9, 0xd1, 0xf9, 0x89, 0x2f, 0x58, 0x46, 0x0b, 0x11,
0x66, 0x67, 0x3a, 0x38, 0x1e, 0xd2, 0x4b, 0xa1, 0x8f, 0x93, 0xdf, 0x00, 0xde, 0x7b, 0xdf, 0x61,
0xde, 0xf1, 0x94, 0xd0, 0xdc, 0xf9, 0x04, 0x07, 0xed, 0x85, 0x11, 0x38, 0x02, 0xd3, 0x3b, 0xcf,
0xc7, 0x9e, 0xa6, 0x79, 0x3d, 0xcd, 0xfb, 0xd0, 0xd3, 0x66, 0x4f, 0x57, 0x12, 0x5b, 0xb5, 0xc4,
0x2a, 0xdf, 0x48, 0x7c, 0xff, 0x32, 0x4b, 0x5f, 0x4d, 0x5a, 0xf1, 0x24, 0x14, 0x22, 0x9f, 0x5c,
0xfd, 0xc2, 0xa0, 0x5e, 0xbb, 0x43, 0xe3, 0x04, 0x2a, 0xe9, 0xbc, 0x81, 0x36, 0x23, 0x23, 0xfb,
0x08, 0x4c, 0x87, 0x33, 0x6f, 0x23, 0xb1, 0xbd, 0x98, 0xd7, 0x12, 0xdb, 0x8c, 0x34, 0x12, 0xdf,
0x55, 0x0c, 0x46, 0x34, 0xa1, 0x5e, 0xbb, 0x07, 0xdd, 0xf9, 0x5b, 0xe9, 0xda, 0x8b, 0x79, 0x60,
0x33, 0xe2, 0xbc, 0x85, 0xb7, 0xd2, 0x30, 0xa2, 0xe9, 0x68, 0x4f, 0x21, 0x1e, 0xd7, 0x12, 0x6b,
0xa3, 0x91, 0xf8, 0x81, 0xba, 0xaf, 0x94, 0x41, 0xc0, 0xad, 0x0c, 0x74, 0x70, 0x72, 0xbd, 0xb7,
0xed, 0x3d, 0xa7, 0x17, 0x2c, 0xa6, 0xff, 0xa1, 0xf7, 0x35, 0x30, 0xc5, 0x0f, 0x67, 0x5f, 0x40,
0x4b, 0xf9, 0x29, 0xf1, 0xcb, 0x84, 0x89, 0xd3, 0xf3, 0xc8, 0x8b, 0x79, 0xe6, 0x17, 0x9f, 0x97,
0xb1, 0x38, 0x65, 0xcb, 0x64, 0xe7, 0xd4, 0x7e, 0x70, 0xf5, 0x88, 0x98, 0xa7, 0x9e, 0x7e, 0xeb,
0x62, 0x6e, 0x56, 0xbb, 0x4d, 0x3a, 0xe7, 0x6f, 0xdb, 0x35, 0x6b, 0xd7, 0xe4, 0xbe, 0x96, 0x2e,
0xd8, 0xd9, 0xf2, 0x35, 0x1c, 0x2c, 0xc3, 0x8c, 0x76, 0x53, 0x4e, 0xdb, 0x56, 0xad, 0x36, 0xad,
0x5a, 0x61, 0x78, 0x43, 0xa3, 0x02, 0x95, 0x72, 0x8e, 0xe1, 0x41, 0x48, 0x48, 0x4e, 0x8b, 0x62,
0x34, 0x50, 0x80, 0x67, 0xb5, 0xc4, 0xbd, 0xd5, 0x48, 0xec, 0x28, 0x46, 0xa7, 0x0d, 0xe6, 0x70,
0xd7, 0x08, 0xfa, 0xf8, 0xec, 0x78, 0x75, 0x83, 0xac, 0xf2, 0x06, 0x59, 0xab, 0x0d, 0x02, 0xe5,
0x06, 0x81, 0xab, 0x0a, 0x59, 0xdf, 0x2b, 0x04, 0xca, 0x0a, 0x59, 0x3f, 0x2a, 0x64, 0x7d, 0x7c,
0xf4, 0x0f, 0x53, 0xe9, 0x9f, 0x20, 0xda, 0x57, 0x93, 0xbd, 0xf8, 0x13, 0x00, 0x00, 0xff, 0xff,
0xd0, 0xf0, 0x82, 0x78, 0x30, 0x03, 0x00, 0x00,
}
func (m *ObservedFolder) Marshal() (dAtA []byte, err error) {
size := m.ProtoSize()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ObservedFolder) MarshalTo(dAtA []byte) (int, error) {
size := m.ProtoSize()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ObservedFolder) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Label) > 0 {
i -= len(m.Label)
copy(dAtA[i:], m.Label)
i = encodeVarintObserved(dAtA, i, uint64(len(m.Label)))
i--
dAtA[i] = 0x1a
}
if len(m.ID) > 0 {
i -= len(m.ID)
copy(dAtA[i:], m.ID)
i = encodeVarintObserved(dAtA, i, uint64(len(m.ID)))
i--
dAtA[i] = 0x12
}
n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
if err1 != nil {
return 0, err1
}
i -= n1
i = encodeVarintObserved(dAtA, i, uint64(n1))
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func (m *ObservedDevice) Marshal() (dAtA []byte, err error) {
size := m.ProtoSize()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ObservedDevice) MarshalTo(dAtA []byte) (int, error) {
size := m.ProtoSize()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ObservedDevice) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Address) > 0 {
i -= len(m.Address)
copy(dAtA[i:], m.Address)
i = encodeVarintObserved(dAtA, i, uint64(len(m.Address)))
i--
dAtA[i] = 0x22
}
if len(m.Name) > 0 {
i -= len(m.Name)
copy(dAtA[i:], m.Name)
i = encodeVarintObserved(dAtA, i, uint64(len(m.Name)))
i--
dAtA[i] = 0x1a
}
{
size := m.ID.ProtoSize()
i -= size
if _, err := m.ID.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
i = encodeVarintObserved(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
n2, err2 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
if err2 != nil {
return 0, err2
}
i -= n2
i = encodeVarintObserved(dAtA, i, uint64(n2))
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func encodeVarintObserved(dAtA []byte, offset int, v uint64) int {
offset -= sovObserved(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *ObservedFolder) ProtoSize() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
n += 1 + l + sovObserved(uint64(l))
l = len(m.ID)
if l > 0 {
n += 1 + l + sovObserved(uint64(l))
}
l = len(m.Label)
if l > 0 {
n += 1 + l + sovObserved(uint64(l))
}
return n
}
func (m *ObservedDevice) ProtoSize() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
n += 1 + l + sovObserved(uint64(l))
l = m.ID.ProtoSize()
n += 1 + l + sovObserved(uint64(l))
l = len(m.Name)
if l > 0 {
n += 1 + l + sovObserved(uint64(l))
}
l = len(m.Address)
if l > 0 {
n += 1 + l + sovObserved(uint64(l))
}
return n
}
func sovObserved(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozObserved(x uint64) (n int) {
return sovObserved(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *ObservedFolder) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ObservedFolder: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ObservedFolder: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthObserved
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthObserved
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthObserved
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthObserved
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Label", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthObserved
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthObserved
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Label = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipObserved(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthObserved
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ObservedDevice) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ObservedDevice: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ObservedDevice: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthObserved
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthObserved
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthObserved
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthObserved
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.ID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthObserved
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthObserved
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Name = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowObserved
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthObserved
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthObserved
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Address = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipObserved(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthObserved
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipObserved(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowObserved
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowObserved
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowObserved
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthObserved
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupObserved
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthObserved
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthObserved = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowObserved = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupObserved = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -16,6 +16,81 @@ import (
"github.com/syncthing/syncthing/lib/structutil"
)
type OptionsConfiguration struct {
RawListenAddresses []string `json:"listenAddresses" xml:"listenAddress" default:"default"`
RawGlobalAnnServers []string `json:"globalAnnounceServers" xml:"globalAnnounceServer" default:"default"`
GlobalAnnEnabled bool `json:"globalAnnounceEnabled" xml:"globalAnnounceEnabled" default:"true"`
LocalAnnEnabled bool `json:"localAnnounceEnabled" xml:"localAnnounceEnabled" default:"true"`
LocalAnnPort int `json:"localAnnouncePort" xml:"localAnnouncePort" default:"21027"`
LocalAnnMCAddr string `json:"localAnnounceMCAddr" xml:"localAnnounceMCAddr" default:"[ff12::8384]:21027"`
MaxSendKbps int `json:"maxSendKbps" xml:"maxSendKbps"`
MaxRecvKbps int `json:"maxRecvKbps" xml:"maxRecvKbps"`
ReconnectIntervalS int `json:"reconnectionIntervalS" xml:"reconnectionIntervalS" default:"60"`
RelaysEnabled bool `json:"relaysEnabled" xml:"relaysEnabled" default:"true"`
RelayReconnectIntervalM int `json:"relayReconnectIntervalM" xml:"relayReconnectIntervalM" default:"10"`
StartBrowser bool `json:"startBrowser" xml:"startBrowser" default:"true"`
NATEnabled bool `json:"natEnabled" xml:"natEnabled" default:"true"`
NATLeaseM int `json:"natLeaseMinutes" xml:"natLeaseMinutes" default:"60"`
NATRenewalM int `json:"natRenewalMinutes" xml:"natRenewalMinutes" default:"30"`
NATTimeoutS int `json:"natTimeoutSeconds" xml:"natTimeoutSeconds" default:"10"`
URAccepted int `json:"urAccepted" xml:"urAccepted"`
URSeen int `json:"urSeen" xml:"urSeen"`
URUniqueID string `json:"urUniqueId" xml:"urUniqueID"`
URURL string `json:"urURL" xml:"urURL" default:"https://data.syncthing.net/newdata"`
URPostInsecurely bool `json:"urPostInsecurely" xml:"urPostInsecurely" default:"false"`
URInitialDelayS int `json:"urInitialDelayS" xml:"urInitialDelayS" default:"1800"`
AutoUpgradeIntervalH int `json:"autoUpgradeIntervalH" xml:"autoUpgradeIntervalH" default:"12"`
UpgradeToPreReleases bool `json:"upgradeToPreReleases" xml:"upgradeToPreReleases"`
KeepTemporariesH int `json:"keepTemporariesH" xml:"keepTemporariesH" default:"24"`
CacheIgnoredFiles bool `json:"cacheIgnoredFiles" xml:"cacheIgnoredFiles" default:"false"`
ProgressUpdateIntervalS int `json:"progressUpdateIntervalS" xml:"progressUpdateIntervalS" default:"5"`
LimitBandwidthInLan bool `json:"limitBandwidthInLan" xml:"limitBandwidthInLan" default:"false"`
MinHomeDiskFree Size `json:"minHomeDiskFree" xml:"minHomeDiskFree" default:"1 %"`
ReleasesURL string `json:"releasesURL" xml:"releasesURL" default:"https://upgrades.syncthing.net/meta.json"`
AlwaysLocalNets []string `json:"alwaysLocalNets" xml:"alwaysLocalNet"`
OverwriteRemoteDevNames bool `json:"overwriteRemoteDeviceNamesOnConnect" xml:"overwriteRemoteDeviceNamesOnConnect" default:"false"`
TempIndexMinBlocks int `json:"tempIndexMinBlocks" xml:"tempIndexMinBlocks" default:"10"`
UnackedNotificationIDs []string `json:"unackedNotificationIDs" xml:"unackedNotificationID"`
TrafficClass int `json:"trafficClass" xml:"trafficClass"`
DeprecatedDefaultFolderPath string `json:"-" xml:"defaultFolderPath,omitempty"` // Deprecated: Do not use.
SetLowPriority bool `json:"setLowPriority" xml:"setLowPriority" default:"true"`
RawMaxFolderConcurrency int `json:"maxFolderConcurrency" xml:"maxFolderConcurrency"`
CRURL string `json:"crURL" xml:"crashReportingURL" default:"https://crash.syncthing.net/newcrash"`
CREnabled bool `json:"crashReportingEnabled" xml:"crashReportingEnabled" default:"true"`
StunKeepaliveStartS int `json:"stunKeepaliveStartS" xml:"stunKeepaliveStartS" default:"180"`
StunKeepaliveMinS int `json:"stunKeepaliveMinS" xml:"stunKeepaliveMinS" default:"20"`
RawStunServers []string `json:"stunServers" xml:"stunServer" default:"default"`
DatabaseTuning Tuning `json:"databaseTuning" xml:"databaseTuning" restart:"true"`
RawMaxCIRequestKiB int `json:"maxConcurrentIncomingRequestKiB" xml:"maxConcurrentIncomingRequestKiB"`
AnnounceLANAddresses bool `json:"announceLANAddresses" xml:"announceLANAddresses" default:"true"`
SendFullIndexOnUpgrade bool `json:"sendFullIndexOnUpgrade" xml:"sendFullIndexOnUpgrade"`
FeatureFlags []string `json:"featureFlags" xml:"featureFlag"`
// The number of connections at which we stop trying to connect to more
// devices, zero meaning no limit. Does not affect incoming connections.
ConnectionLimitEnough int `json:"connectionLimitEnough" xml:"connectionLimitEnough"`
// The maximum number of connections which we will allow in total, zero
// meaning no limit. Affects incoming connections and prevents
// attempting outgoing connections.
ConnectionLimitMax int `json:"connectionLimitMax" xml:"connectionLimitMax"`
// When set, this allows TLS 1.2 on sync connections, where we otherwise
// default to TLS 1.3+ only.
InsecureAllowOldTLSVersions bool `json:"insecureAllowOldTLSVersions" xml:"insecureAllowOldTLSVersions"`
ConnectionPriorityTCPLAN int `json:"connectionPriorityTcpLan" xml:"connectionPriorityTcpLan" default:"10"`
ConnectionPriorityQUICLAN int `json:"connectionPriorityQuicLan" xml:"connectionPriorityQuicLan" default:"20"`
ConnectionPriorityTCPWAN int `json:"connectionPriorityTcpWan" xml:"connectionPriorityTcpWan" default:"30"`
ConnectionPriorityQUICWAN int `json:"connectionPriorityQuicWan" xml:"connectionPriorityQuicWan" default:"40"`
ConnectionPriorityRelay int `json:"connectionPriorityRelay" xml:"connectionPriorityRelay" default:"50"`
ConnectionPriorityUpgradeThreshold int `json:"connectionPriorityUpgradeThreshold" xml:"connectionPriorityUpgradeThreshold" default:"0"`
// Legacy deprecated
DeprecatedUPnPEnabled bool `json:"-" xml:"upnpEnabled,omitempty"` // Deprecated: Do not use.
DeprecatedUPnPLeaseM int `json:"-" xml:"upnpLeaseMinutes,omitempty"` // Deprecated: Do not use.
DeprecatedUPnPRenewalM int `json:"-" xml:"upnpRenewalMinutes,omitempty"` // Deprecated: Do not use.
DeprecatedUPnPTimeoutS int `json:"-" xml:"upnpTimeoutSeconds,omitempty"` // Deprecated: Do not use.
DeprecatedRelayServers []string `json:"-" xml:"relayServer,omitempty"` // Deprecated: Do not use.
DeprecatedMinHomeDiskFreePct float64 `json:"-" xml:"minHomeDiskFreePct,omitempty"` // Deprecated: Do not use.
DeprecatedMaxConcurrentScans int `json:"-" xml:"maxConcurrentScans,omitempty"` // Deprecated: Do not use.
}
func (opts OptionsConfiguration) Copy() OptionsConfiguration {
optsCopy := opts
optsCopy.RawListenAddresses = make([]string, len(opts.RawListenAddresses))

View File

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,17 @@
package config
type PullOrder int32
const (
PullOrderRandom PullOrder = 0
PullOrderAlphabetic PullOrder = 1
PullOrderSmallestFirst PullOrder = 2
PullOrderLargestFirst PullOrder = 3
PullOrderOldestFirst PullOrder = 4
PullOrderNewestFirst PullOrder = 5
)
func (o PullOrder) String() string {
switch o {
case PullOrderRandom:

View File

@@ -1,87 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/pullorder.proto
package config
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type PullOrder int32
const (
PullOrderRandom PullOrder = 0
PullOrderAlphabetic PullOrder = 1
PullOrderSmallestFirst PullOrder = 2
PullOrderLargestFirst PullOrder = 3
PullOrderOldestFirst PullOrder = 4
PullOrderNewestFirst PullOrder = 5
)
var PullOrder_name = map[int32]string{
0: "PULL_ORDER_RANDOM",
1: "PULL_ORDER_ALPHABETIC",
2: "PULL_ORDER_SMALLEST_FIRST",
3: "PULL_ORDER_LARGEST_FIRST",
4: "PULL_ORDER_OLDEST_FIRST",
5: "PULL_ORDER_NEWEST_FIRST",
}
var PullOrder_value = map[string]int32{
"PULL_ORDER_RANDOM": 0,
"PULL_ORDER_ALPHABETIC": 1,
"PULL_ORDER_SMALLEST_FIRST": 2,
"PULL_ORDER_LARGEST_FIRST": 3,
"PULL_ORDER_OLDEST_FIRST": 4,
"PULL_ORDER_NEWEST_FIRST": 5,
}
func (PullOrder) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_2fa3f5222a7755bf, []int{0}
}
func init() {
proto.RegisterEnum("config.PullOrder", PullOrder_name, PullOrder_value)
}
func init() { proto.RegisterFile("lib/config/pullorder.proto", fileDescriptor_2fa3f5222a7755bf) }
var fileDescriptor_2fa3f5222a7755bf = []byte{
// 347 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0xd1, 0xbf, 0x4a, 0xc3, 0x40,
0x1c, 0xc0, 0xf1, 0xa4, 0xd6, 0x82, 0xb7, 0x58, 0x53, 0x6b, 0xdb, 0x1b, 0x8e, 0x80, 0x93, 0x1d,
0x1a, 0x50, 0x44, 0x1c, 0x53, 0x9b, 0x6a, 0xf1, 0xda, 0x94, 0xa4, 0x22, 0xb8, 0x94, 0x24, 0x4d,
0xd3, 0xc0, 0x35, 0x17, 0xf2, 0x07, 0xf1, 0x15, 0x32, 0xf9, 0x02, 0x01, 0x07, 0x07, 0x1f, 0xa5,
0x63, 0xc1, 0xc5, 0xb5, 0xcd, 0x8b, 0x88, 0x29, 0x26, 0x41, 0x70, 0xfb, 0xdd, 0x8f, 0xef, 0xe7,
0x96, 0x1f, 0x80, 0xc4, 0xd6, 0x05, 0x83, 0x3a, 0x73, 0xdb, 0x12, 0xdc, 0x90, 0x10, 0xea, 0xcd,
0x4c, 0xaf, 0xe3, 0x7a, 0x34, 0xa0, 0x5c, 0x65, 0xb7, 0x87, 0xa7, 0x9e, 0xe9, 0x52, 0x5f, 0x48,
0x97, 0x7a, 0x38, 0x17, 0x2c, 0x6a, 0xd1, 0xf4, 0x91, 0x4e, 0xbb, 0xb8, 0xfd, 0x59, 0x02, 0x07,
0xe3, 0x90, 0x10, 0xf9, 0xe7, 0x03, 0xae, 0x0d, 0x8e, 0xc6, 0x0f, 0x18, 0x4f, 0x65, 0xa5, 0x27,
0x29, 0x53, 0x45, 0x1c, 0xf5, 0xe4, 0x61, 0x95, 0x81, 0xb5, 0x28, 0xe6, 0x0f, 0xb3, 0x4a, 0xd1,
0x9c, 0x19, 0x5d, 0x72, 0xe7, 0xa0, 0x5e, 0x68, 0x45, 0x3c, 0xbe, 0x13, 0xbb, 0xd2, 0x64, 0x70,
0x53, 0x65, 0x61, 0x23, 0x8a, 0xf9, 0x5a, 0xd6, 0x8b, 0xc4, 0x5d, 0x68, 0xba, 0x19, 0xd8, 0x06,
0x77, 0x0d, 0x5a, 0x05, 0xa3, 0x0e, 0x45, 0x8c, 0x25, 0x75, 0x32, 0xed, 0x0f, 0x14, 0x75, 0x52,
0x2d, 0x41, 0x18, 0xc5, 0xfc, 0x49, 0xe6, 0xd4, 0xa5, 0x46, 0x88, 0xe9, 0x07, 0x7d, 0xdb, 0xf3,
0x03, 0xee, 0x0a, 0x34, 0x0b, 0x14, 0x8b, 0xca, 0x6d, 0x2e, 0xf7, 0x60, 0x2b, 0x8a, 0xf9, 0x7a,
0x26, 0xb1, 0xe6, 0x59, 0x19, 0xbc, 0x04, 0x8d, 0x02, 0x94, 0x71, 0x2f, 0x77, 0x65, 0xd8, 0x8c,
0x62, 0xfe, 0x38, 0x73, 0x32, 0x99, 0xfd, 0xc3, 0x46, 0xd2, 0x63, 0xce, 0xf6, 0xff, 0xb0, 0x91,
0xf9, 0xfc, 0xcb, 0x60, 0xf9, 0xe3, 0x1d, 0x31, 0xdd, 0xfb, 0xd5, 0x06, 0x31, 0xeb, 0x0d, 0x62,
0x56, 0x5b, 0xc4, 0xae, 0xb7, 0x88, 0x7d, 0x4d, 0x10, 0xf3, 0x96, 0x20, 0x76, 0x9d, 0x20, 0xe6,
0x2b, 0x41, 0xcc, 0xd3, 0x99, 0x65, 0x07, 0x8b, 0x50, 0xef, 0x18, 0x74, 0x29, 0xf8, 0x2f, 0x8e,
0x11, 0x2c, 0x6c, 0xc7, 0x2a, 0x4c, 0xf9, 0x7d, 0xf5, 0x4a, 0x7a, 0xa9, 0x8b, 0xef, 0x00, 0x00,
0x00, 0xff, 0xff, 0x09, 0x68, 0xa0, 0x7d, 0xf4, 0x01, 0x00, 0x00,
}

View File

@@ -14,6 +14,11 @@ import (
"github.com/syncthing/syncthing/lib/fs"
)
type Size struct {
Value float64 `json:"value" xml:",chardata"`
Unit string `json:"unit" xml:"unit,attr"`
}
func ParseSize(s string) (Size, error) {
s = strings.TrimSpace(s)
if s == "" {
@@ -24,7 +29,7 @@ func ParseSize(s string) (Size, error) {
for i := 0; i < len(s) && (s[i] >= '0' && s[i] <= '9' || s[i] == '.' || s[i] == ','); i++ {
num = s[:i+1]
}
var i = len(num)
i := len(num)
for i < len(s) && s[i] == ' ' {
i++
}

View File

@@ -1,336 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: lib/config/size.proto
package config
import (
encoding_binary "encoding/binary"
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
_ "github.com/syncthing/syncthing/proto/ext"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type Size struct {
Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value" xml:",chardata"`
Unit string `protobuf:"bytes,2,opt,name=unit,proto3" json:"unit" xml:"unit,attr"`
}
func (m *Size) Reset() { *m = Size{} }
func (*Size) ProtoMessage() {}
func (*Size) Descriptor() ([]byte, []int) {
return fileDescriptor_4d75cb8f619bd299, []int{0}
}
func (m *Size) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Size) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Size.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Size) XXX_Merge(src proto.Message) {
xxx_messageInfo_Size.Merge(m, src)
}
func (m *Size) XXX_Size() int {
return m.ProtoSize()
}
func (m *Size) XXX_DiscardUnknown() {
xxx_messageInfo_Size.DiscardUnknown(m)
}
var xxx_messageInfo_Size proto.InternalMessageInfo
func init() {
proto.RegisterType((*Size)(nil), "config.Size")
}
func init() { proto.RegisterFile("lib/config/size.proto", fileDescriptor_4d75cb8f619bd299) }
var fileDescriptor_4d75cb8f619bd299 = []byte{
// 251 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0xc9, 0x4c, 0xd2,
0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2f, 0xce, 0xac, 0x4a, 0xd5, 0x2b, 0x28, 0xca, 0x2f,
0xc9, 0x17, 0x62, 0x83, 0x08, 0x49, 0x29, 0x17, 0xa5, 0x16, 0xe4, 0x17, 0xeb, 0x83, 0x05, 0x93,
0x4a, 0xd3, 0xf4, 0xd3, 0xf3, 0xd3, 0xf3, 0xc1, 0x1c, 0x30, 0x0b, 0xa2, 0x58, 0x8a, 0x33, 0xb5,
0xa2, 0x04, 0xc2, 0x54, 0xea, 0x66, 0xe4, 0x62, 0x09, 0xce, 0xac, 0x4a, 0x15, 0xb2, 0xe7, 0x62,
0x2d, 0x4b, 0xcc, 0x29, 0x4d, 0x95, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x74, 0xd2, 0x7c, 0x75, 0x4f,
0x1e, 0x22, 0xf0, 0xe9, 0x9e, 0x3c, 0x7f, 0x45, 0x6e, 0x8e, 0x95, 0x92, 0x4e, 0x72, 0x46, 0x62,
0x51, 0x4a, 0x62, 0x49, 0xa2, 0xd2, 0xab, 0xf3, 0x2a, 0x9c, 0x70, 0x5e, 0x10, 0x44, 0x99, 0x90,
0x0d, 0x17, 0x4b, 0x69, 0x5e, 0x66, 0x89, 0x04, 0x93, 0x02, 0xa3, 0x06, 0xa7, 0x93, 0xc6, 0xab,
0x7b, 0xf2, 0x60, 0x3e, 0x5c, 0x3b, 0x88, 0xa3, 0x93, 0x58, 0x52, 0x52, 0x04, 0xd6, 0x0e, 0xe7,
0x05, 0x81, 0x55, 0x59, 0xb1, 0xcc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x7d, 0xe2, 0xa1, 0x1c, 0xc3,
0x85, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c,
0xc3, 0x82, 0xc7, 0x72, 0x8c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x99,
0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x5f, 0x5c, 0x99, 0x97, 0x5c, 0x92,
0x91, 0x99, 0x97, 0x8e, 0xc4, 0x42, 0x84, 0x4e, 0x12, 0x1b, 0xd8, 0x87, 0xc6, 0x80, 0x00, 0x00,
0x00, 0xff, 0xff, 0x65, 0x1e, 0xa3, 0x25, 0x32, 0x01, 0x00, 0x00,
}
func (m *Size) Marshal() (dAtA []byte, err error) {
size := m.ProtoSize()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Size) MarshalTo(dAtA []byte) (int, error) {
size := m.ProtoSize()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Size) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Unit) > 0 {
i -= len(m.Unit)
copy(dAtA[i:], m.Unit)
i = encodeVarintSize(dAtA, i, uint64(len(m.Unit)))
i--
dAtA[i] = 0x12
}
if m.Value != 0 {
i -= 8
encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value))))
i--
dAtA[i] = 0x9
}
return len(dAtA) - i, nil
}
func encodeVarintSize(dAtA []byte, offset int, v uint64) int {
offset -= sovSize(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *Size) ProtoSize() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Value != 0 {
n += 9
}
l = len(m.Unit)
if l > 0 {
n += 1 + l + sovSize(uint64(l))
}
return n
}
func sovSize(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozSize(x uint64) (n int) {
return sovSize(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *Size) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSize
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Size: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Size: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 1 {
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
}
var v uint64
if (iNdEx + 8) > l {
return io.ErrUnexpectedEOF
}
v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:]))
iNdEx += 8
m.Value = float64(math.Float64frombits(v))
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Unit", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSize
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSize
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthSize
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Unit = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSize(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthSize
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipSize(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSize
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSize
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSize
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthSize
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupSize
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthSize
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthSize = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowSize = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupSize = fmt.Errorf("proto: unexpected end of group")
)

View File

@@ -6,6 +6,14 @@
package config
type Tuning int32
const (
TuningAuto Tuning = 0
TuningSmall Tuning = 1
TuningLarge Tuning = 2
)
func (t Tuning) String() string {
switch t {
case TuningAuto:

Some files were not shown because too many files have changed in this diff Show More