Compare commits

...

25 Commits

Author SHA1 Message Date
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
131 changed files with 847 additions and 659 deletions

View File

@@ -725,6 +725,88 @@ 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-'))
environment: signing
needs:
- basics
- package-debian
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- 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: Prepare signing key
run: |
echo "$APT_GPG_KEYRING_BASE64" | base64 -d > keyring.pgp
env:
APT_GPG_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
- name: Update archive
uses: docker://ghcr.io/kastelo/ezapt:latest
with:
args:
--add packages
--dists dists
--keyring keyring.pgp
- 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
#

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

@@ -146,6 +146,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 +190,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 +320,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>

144
build.go
View File

@@ -97,40 +97,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,21 +142,21 @@ 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"},
},
@@ -169,23 +169,23 @@ 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": {
@@ -196,16 +196,16 @@ var targets = map[string]target{
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},
{src: "{{binary}}", dst: "{{binary}}", perm: 0o755},
{src: "cmd/infra/strelaypoolsrv/README.md", dst: "README.txt", perm: 0o644},
{src: "cmd/infra/strelaypoolsrv/LICENSE", dst: "LICENSE.txt", perm: 0o644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0o644},
},
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},
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0o755},
{src: "cmd/infra/strelaypoolsrv/README.md", dst: "deb/usr/share/doc/syncthing-relaypoolsrv/README.txt", perm: 0o644},
{src: "cmd/infra/strelaypoolsrv/LICENSE", dst: "deb/usr/share/doc/syncthing-relaypoolsrv/LICENSE.txt", perm: 0o644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing-relaypoolsrv/AUTHORS.txt", perm: 0o644},
},
},
"stupgrades": {
@@ -244,13 +244,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
}
@@ -750,7 +750,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 +809,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 +869,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)
}
@@ -930,7 +930,7 @@ func proto() {
path := filepath.Join("repos", "protobuf")
runPrint(goCmd, "install", fmt.Sprintf("github.com/gogo/protobuf/protoc-gen-gogofast@%v", pv))
os.MkdirAll("repos", 0755)
os.MkdirAll("repos", 0o755)
if _, err := os.Stat(path); err != nil {
runPrint("git", "clone", repo, path)
@@ -1427,7 +1427,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)

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

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

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

@@ -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")

28
go.mod
View File

@@ -27,26 +27,26 @@ require (
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/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.0
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/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/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.28.0
golang.org/x/net v0.30.0
golang.org/x/sys v0.26.0
golang.org/x/text v0.19.0
golang.org/x/time v0.7.0
golang.org/x/tools v0.26.0
google.golang.org/protobuf v1.35.1
sigs.k8s.io/yaml v1.4.0
)
@@ -65,12 +65,12 @@ require (
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
@@ -88,10 +88,10 @@ require (
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.9.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/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/sync v0.8.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

59
go.sum
View File

@@ -2,7 +2,7 @@ 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/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
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=
@@ -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=
@@ -89,8 +88,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
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=
@@ -138,8 +137,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
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=
@@ -196,8 +195,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 +205,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.0 h1:2TCyvBrMu1Z25rvIAlnp2dPT4lgh/uTqLqiXVpp5AeU=
github.com/quic-go/quic-go v0.48.0/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=
@@ -244,11 +243,11 @@ github.com/thejerf/suture/v4 v4.0.5 h1:F1E/4FZwXWqvlWDKEUo6/ndLtxGAUzMmNqkrMknZb
github.com/thejerf/suture/v4 v4.0.5/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=
@@ -271,10 +270,10 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
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/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
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.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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=
@@ -298,8 +297,8 @@ 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.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.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
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=
@@ -337,8 +336,8 @@ 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.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.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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=
@@ -352,10 +351,10 @@ 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.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.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.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=
@@ -363,8 +362,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
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.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
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 +377,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.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.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

@@ -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:": "내용:",
@@ -458,7 +458,7 @@
"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}}\" 기기와 연동하려면 아래의 식별자를 이용해 본인의 기기에서 새로운 기기를 추가하십시오.",

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 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>

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') {

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>

View File

@@ -1165,6 +1165,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 +1232,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 +1245,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 +1506,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 +1525,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)
}

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

@@ -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"
}

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{
@@ -116,11 +115,19 @@ func New(myID protocol.DeviceID) Configuration {
}
func (cfg *Configuration) ProbeFreePorts() error {
port, err := getFreePort("127.0.0.1", DefaultGUIPort)
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 = fmt.Sprintf("127.0.0.1:%d", port)
cfg.GUI.RawAddress = net.JoinHostPort(guiHost, strconv.Itoa(port))
port, err = getFreePort("0.0.0.0", DefaultTCPPort)
if err != nil {

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

@@ -24,7 +24,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

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("connections", "Connection handling")
)
var l = logger.DefaultLogger.NewFacility("connections", "Connection handling")

View File

@@ -21,8 +21,10 @@ import (
"golang.org/x/time/rate"
)
var device1, device2, device3, device4 protocol.DeviceID
var dev1Conf, dev2Conf, dev3Conf, dev4Conf config.DeviceConfiguration
var (
device1, device2, device3, device4 protocol.DeviceID
dev1Conf, dev2Conf, dev3Conf, dev4Conf config.DeviceConfiguration
)
func init() {
device1, _ = protocol.DeviceIDFromString("AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ")

View File

@@ -11,14 +11,12 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
metricDeviceActiveConnections = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "syncthing",
Subsystem: "connections",
Name: "active",
Help: "Number of currently active connections, per device. If value is 0, the device is disconnected.",
}, []string{"device"})
)
var metricDeviceActiveConnections = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "syncthing",
Subsystem: "connections",
Name: "active",
Help: "Number of currently active connections, per device. If value is 0, the device is disconnected.",
}, []string{"device"})
func registerDeviceMetrics(deviceID string) {
// Register metrics for this device, so that counters & gauges are present even

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("backend", "The database backend")
)
var l = logger.DefaultLogger.NewFacility("backend", "The database backend")

View File

@@ -13,8 +13,10 @@ import (
"github.com/syncthing/syncthing/lib/protocol"
)
var f1, f2, f3 protocol.FileInfo
var folders = []string{"folder1", "folder2"}
var (
f1, f2, f3 protocol.FileInfo
folders = []string{"folder1", "folder2"}
)
func init() {
blocks := genBlocks(30)

View File

@@ -159,7 +159,6 @@ func init() {
func TestUpdate0to3(t *testing.T) {
ldb, err := openJSONS("testdata/v0.14.45-update0to3.db.jsons")
if err != nil {
t.Fatal(err)
}

View File

@@ -10,9 +10,7 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("db", "The database layer")
)
var l = logger.DefaultLogger.NewFacility("db", "The database layer")
func shouldDebug() bool {
return l.ShouldDebug("db")

View File

@@ -55,6 +55,7 @@ func globalList(t testing.TB, s *db.FileSet) []protocol.FileInfo {
})
return fs
}
func globalListPrefixed(t testing.TB, s *db.FileSet, prefix string) []db.FileInfoTruncated {
var fs []db.FileInfoTruncated
snap := snapshot(t, s)

View File

@@ -16,9 +16,7 @@ import (
"golang.org/x/net/proxy"
)
var (
noFallback = os.Getenv("ALL_PROXY_NO_FALLBACK") != ""
)
var noFallback = os.Getenv("ALL_PROXY_NO_FALLBACK") != ""
func init() {
proxy.RegisterDialerType("socks", socksDialerFunction)

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("discover", "Remote device discovery")
)
var l = logger.DefaultLogger.NewFacility("discover", "Remote device discovery")

View File

@@ -244,6 +244,7 @@ type fakeAddressLister struct{}
func (*fakeAddressLister) ExternalAddresses() []string {
return []string{"tcp://0.0.0.0:22000"}
}
func (*fakeAddressLister) AllAddresses() []string {
return []string{"tcp://0.0.0.0:22000", "tcp://192.168.0.1:22000"}
}

View File

@@ -10,6 +10,4 @@ import (
liblogger "github.com/syncthing/syncthing/lib/logger"
)
var (
dl = liblogger.DefaultLogger.NewFacility("events", "Event generation and logging")
)
var dl = liblogger.DefaultLogger.NewFacility("events", "Event generation and logging")

View File

@@ -81,7 +81,6 @@ func TestEventAfterSubscribe(t *testing.T) {
l.Log(DeviceConnected, "foo")
ev, err := s.Poll(timeout)
if err != nil {
t.Fatal("Unexpected error:", err)
}

View File

@@ -40,13 +40,13 @@ func (e basicFileInfo) Mode() FileMode {
}
// Set executable bits on files with executable extensions (.exe, .bat, etc).
if isWindowsExecutable(e.Name()) {
m |= 0111
m |= 0o111
}
// There is no user/group/others in Windows' read-only attribute, and
// all "w" bits are set if the file is not read-only. Do not send these
// group/others-writable bits to other devices in order to avoid
// unexpected world-writable files on other platforms.
m &^= 0022
m &^= 0o022
return FileMode(m)
}

View File

@@ -32,7 +32,7 @@ func readReparseTag(path string) (uint32, error) {
}
defer syscall.CloseHandle(h)
//https://docs.microsoft.com/windows/win32/api/winbase/ns-winbase-file_attribute_tag_info
// https://docs.microsoft.com/windows/win32/api/winbase/ns-winbase-file_attribute_tag_info
const fileAttributeTagInfo = 9
type FILE_ATTRIBUTE_TAG_INFO struct {
FileAttributes uint32
@@ -67,7 +67,7 @@ type dirJunctFileInfo struct {
func (fi *dirJunctFileInfo) Mode() os.FileMode {
// Simulate a directory and not a symlink; also set the execute
// bits so the directory can be traversed Unix-side.
return fi.FileInfo.Mode() ^ junctionPointModeMask | os.ModeDir | 0111
return fi.FileInfo.Mode()&^junctionPointModeMask | os.ModeDir | 0o111
}
func (fi *dirJunctFileInfo) IsDir() bool {
@@ -77,16 +77,19 @@ func (fi *dirJunctFileInfo) IsDir() bool {
var junctionPointModeMask os.FileMode
func init() {
// Per https://tip.golang.org/doc/go1.23#minor_library_changes
// In go1.22 (and go1.23 when GODEBUG=winsymlink=0) Windows' directory
// junctions (aka "mount points") always have ModeSymlink set.
junctionPointModeMask = os.ModeSymlink
if version.Compare(runtime.Version(), "go1.23") >= 0 {
// if GODEBUG=winsymlink=0, then we are in g1.22 mode so let's check for
// os.ModeSymlink as well, as it can't hurt.
// In go1.23 Windows' directory junctions always have ModeIrregular set
// (unless GODEBUG=winsymlink=0).
junctionPointModeMask |= os.ModeIrregular
}
}
func (f *BasicFilesystem) underlyingLstat(name string) (os.FileInfo, error) {
var fi, err = os.Lstat(name)
fi, err := os.Lstat(name)
// There are cases where files are tagged as symlink, but they end up being
// something else. Make sure we properly handle those types.

View File

@@ -34,7 +34,7 @@ func TestChmodFile(t *testing.T) {
fs, dir := setup(t)
path := filepath.Join(dir, "file")
defer os.Chmod(path, 0666)
defer os.Chmod(path, 0o666)
fd, err := os.Create(path)
if err != nil {
@@ -42,19 +42,19 @@ func TestChmodFile(t *testing.T) {
}
fd.Close()
if err := os.Chmod(path, 0666); err != nil {
if err := os.Chmod(path, 0o666); err != nil {
t.Error(err)
}
if stat, err := os.Stat(path); err != nil || stat.Mode()&os.ModePerm != 0666 {
if stat, err := os.Stat(path); err != nil || stat.Mode()&os.ModePerm != 0o666 {
t.Errorf("wrong perm: %t %#o", err == nil, stat.Mode()&os.ModePerm)
}
if err := fs.Chmod("file", 0444); err != nil {
if err := fs.Chmod("file", 0o444); err != nil {
t.Error(err)
}
if stat, err := os.Stat(path); err != nil || stat.Mode()&os.ModePerm != 0444 {
if stat, err := os.Stat(path); err != nil || stat.Mode()&os.ModePerm != 0o444 {
t.Errorf("wrong perm: %t %#o", err == nil, stat.Mode()&os.ModePerm)
}
}
@@ -74,7 +74,7 @@ func TestChownFile(t *testing.T) {
fs, dir := setup(t)
path := filepath.Join(dir, "file")
defer os.Chmod(path, 0666)
defer os.Chmod(path, 0o666)
fd, err := os.Create(path)
if err != nil {
@@ -110,9 +110,9 @@ func TestChmodDir(t *testing.T) {
fs, dir := setup(t)
path := filepath.Join(dir, "dir")
mode := os.FileMode(0755)
mode := os.FileMode(0o755)
if build.IsWindows {
mode = os.FileMode(0777)
mode = os.FileMode(0o777)
}
defer os.Chmod(path, mode)
@@ -129,11 +129,11 @@ func TestChmodDir(t *testing.T) {
t.Errorf("wrong perm: %t %#o", err == nil, stat.Mode()&os.ModePerm)
}
if err := fs.Chmod("dir", 0555); err != nil {
if err := fs.Chmod("dir", 0o555); err != nil {
t.Error(err)
}
if stat, err := os.Stat(path); err != nil || stat.Mode()&os.ModePerm != 0555 {
if stat, err := os.Stat(path); err != nil || stat.Mode()&os.ModePerm != 0o555 {
t.Errorf("wrong perm: %t %#o", err == nil, stat.Mode()&os.ModePerm)
}
}
@@ -221,7 +221,7 @@ func TestDirNames(t *testing.T) {
sort.Strings(testCases)
for _, sub := range testCases {
if err := os.Mkdir(filepath.Join(dir, sub), 0777); err != nil {
if err := os.Mkdir(filepath.Join(dir, sub), 0o777); err != nil {
t.Error(err)
}
}
@@ -256,7 +256,7 @@ func TestNames(t *testing.T) {
t.Errorf("incorrect %s != %s (%v)", stat.Name(), expected, err)
}
if err := fs.Mkdir("dir", 0777); err != nil {
if err := fs.Mkdir("dir", 0o777); err != nil {
t.Error(err)
}
@@ -286,7 +286,7 @@ func TestGlob(t *testing.T) {
filepath.Join("a", "best", "b"),
filepath.Join("a", "best", "c"),
} {
if err := fs.MkdirAll(dirToCreate, 0777); err != nil {
if err := fs.MkdirAll(dirToCreate, 0o777); err != nil {
t.Error(err)
}
}
@@ -572,7 +572,7 @@ func TestRel(t *testing.T) {
func TestXattr(t *testing.T) {
tfs, _ := setup(t)
if err := tfs.Mkdir("/test", 0755); err != nil {
if err := tfs.Mkdir("/test", 0o755); err != nil {
t.Fatal(err)
}

View File

@@ -198,7 +198,7 @@ func (f *BasicFilesystem) Remove(name string) error {
err = os.Remove(name)
if os.IsPermission(err) {
// Try to remove the read-only attribute and try again
if os.Chmod(name, 0600) == nil {
if os.Chmod(name, 0o600) == nil {
err = os.Remove(name)
}
}

View File

@@ -40,7 +40,7 @@ func testRealCase(t *testing.T, fsys Filesystem) {
testFs := newCaseFilesystem(fsys)
comps := []string{"Foo", "bar", "BAZ", "bAs"}
path := filepath.Join(comps...)
testFs.MkdirAll(filepath.Join(comps[:len(comps)-1]...), 0777)
testFs.MkdirAll(filepath.Join(comps[:len(comps)-1]...), 0o777)
fd, err := testFs.Create(path)
if err != nil {
t.Fatal(err)
@@ -93,7 +93,7 @@ func testRealCaseSensitive(t *testing.T, fsys Filesystem) {
names[0] = "foo"
names[1] = strings.ToUpper(names[0])
for _, n := range names {
if err := testFs.MkdirAll(n, 0777); err != nil {
if err := testFs.MkdirAll(n, 0o777); err != nil {
if IsErrCaseConflict(err) {
t.Skip("Filesystem is case-insensitive")
}

View File

@@ -10,9 +10,7 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("fs", "Filesystem access")
)
var l = logger.DefaultLogger.NewFacility("fs", "Filesystem access")
func init() {
logger.DefaultLogger.NewFacility("walkfs", "Filesystem access while walking")

View File

@@ -30,6 +30,7 @@ func (fs *errorFilesystem) DirNames(_ string) ([]string, error) { return nil, fs
func (fs *errorFilesystem) GetXattr(_ string, _ XattrFilter) ([]protocol.Xattr, error) {
return nil, fs.err
}
func (fs *errorFilesystem) SetXattr(_ string, _ []protocol.Xattr, _ XattrFilter) error {
return fs.err
}
@@ -60,6 +61,7 @@ func (*errorFilesystem) SameFile(_, _ FileInfo) bool { return false }
func (fs *errorFilesystem) Watch(_ string, _ Matcher, _ context.Context, _ bool) (<-chan Event, <-chan error, error) {
return nil, nil, fs.err
}
func (fs *errorFilesystem) PlatformData(_ string, _, _ bool, _ XattrFilter) (protocol.PlatformData, error) {
return protocol.PlatformData{}, fs.err
}

View File

@@ -27,7 +27,7 @@ func TestFakeFS(t *testing.T) {
fs := newFakeFilesystem("/foo/bar/baz")
// MkdirAll
err := fs.MkdirAll("dira/dirb", 0755)
err := fs.MkdirAll("dira/dirb", 0o755)
if err != nil {
t.Fatal(err)
}
@@ -37,7 +37,7 @@ func TestFakeFS(t *testing.T) {
}
// Mkdir
err = fs.Mkdir("dira/dirb/dirc", 0755)
err = fs.Mkdir("dira/dirb/dirc", 0o755)
if err != nil {
t.Fatal(err)
}
@@ -190,7 +190,7 @@ type test struct {
}
func TestFakeFSCaseSensitive(t *testing.T) {
var tests = []test{
tests := []test{
{"Read", testFakeFSRead},
{"OpenFile", testFakeFSOpenFile},
{"RemoveAll", testFakeFSRemoveAll},
@@ -201,7 +201,7 @@ func TestFakeFSCaseSensitive(t *testing.T) {
{"DirNames", testDirNames},
{"FileName", testFakeFSFileName},
}
var filesystems = []testFS{
filesystems := []testFS{
{"fakeFS", newFakeFilesystem("/foo")},
}
@@ -214,7 +214,7 @@ func TestFakeFSCaseSensitive(t *testing.T) {
}
func TestFakeFSCaseInsensitive(t *testing.T) {
var tests = []test{
tests := []test{
{"Read", testFakeFSRead},
{"OpenFile", testFakeFSOpenFile},
{"RemoveAll", testFakeFSRemoveAll},
@@ -236,7 +236,7 @@ func TestFakeFSCaseInsensitive(t *testing.T) {
{"FileNameInsens", testFakeFSFileNameInsens},
}
var filesystems = []testFS{
filesystems := []testFS{
{"fakeFS", newFakeFilesystem("/foobar?insens=true")},
}
@@ -287,7 +287,7 @@ func runTests(t *testing.T, tests []test, filesystems []testFS) {
func testFakeFSCaseInsensitive(t *testing.T, fs Filesystem) {
bs1 := []byte("test")
err := fs.Mkdir("/fUbar", 0755)
err := fs.Mkdir("/fUbar", 0o755)
if err != nil {
t.Fatal(err)
}
@@ -327,12 +327,12 @@ func testFakeFSCaseInsensitive(t *testing.T, fs Filesystem) {
}
func testFakeFSCaseInsensitiveMkdirAll(t *testing.T, fs Filesystem) {
err := fs.MkdirAll("/fOO/Bar/bAz", 0755)
err := fs.MkdirAll("/fOO/Bar/bAz", 0o755)
if err != nil {
t.Fatal(err)
}
fd, err := fs.OpenFile("/foo/BaR/BaZ/tESt", os.O_CREATE, 0644)
fd, err := fs.OpenFile("/foo/BaR/BaZ/tESt", os.O_CREATE, 0o644)
if err != nil {
t.Fatal(err)
}
@@ -430,7 +430,7 @@ func testFakeFSStatInsens(t *testing.T, fs Filesystem) {
}
func testFakeFSFileName(t *testing.T, fs Filesystem) {
var testCases = []struct {
testCases := []struct {
create string
open string
}{
@@ -458,7 +458,7 @@ func testFakeFSFileName(t *testing.T, fs Filesystem) {
}
func testFakeFSFileNameInsens(t *testing.T, fs Filesystem) {
var testCases = []struct {
testCases := []struct {
create string
open string
}{
@@ -486,7 +486,7 @@ func testFakeFSFileNameInsens(t *testing.T, fs Filesystem) {
}
func testFakeFSRename(t *testing.T, fs Filesystem) {
if err := fs.MkdirAll("/foo/bar/baz", 0755); err != nil {
if err := fs.MkdirAll("/foo/bar/baz", 0o755); err != nil {
t.Fatal(err)
}
@@ -500,7 +500,7 @@ func testFakeFSRename(t *testing.T, fs Filesystem) {
t.Errorf("rename to non-existent dir gave no error")
}
if err := fs.MkdirAll("/baz/bar/foo", 0755); err != nil {
if err := fs.MkdirAll("/baz/bar/foo", 0o755); err != nil {
t.Fatal(err)
}
@@ -508,7 +508,7 @@ func testFakeFSRename(t *testing.T, fs Filesystem) {
t.Fatal(err)
}
var dirs = []struct {
dirs := []struct {
dir string
files []string
}{
@@ -531,11 +531,11 @@ func testFakeFSRename(t *testing.T, fs Filesystem) {
}
func testFakeFSRenameInsensitive(t *testing.T, fs Filesystem) {
if err := fs.MkdirAll("/baz/bar/foo", 0755); err != nil {
if err := fs.MkdirAll("/baz/bar/foo", 0o755); err != nil {
t.Fatal(err)
}
if err := fs.MkdirAll("/foO/baR/baZ", 0755); err != nil {
if err := fs.MkdirAll("/foO/baR/baZ", 0o755); err != nil {
t.Fatal(err)
}
@@ -550,7 +550,7 @@ func testFakeFSRenameInsensitive(t *testing.T, fs Filesystem) {
t.Fatal(err)
}
var dirs = []struct {
dirs := []struct {
dir string
files []string
}{
@@ -582,7 +582,7 @@ func testFakeFSRenameInsensitive(t *testing.T, fs Filesystem) {
}
func testFakeFSMkdir(t *testing.T, fs Filesystem) {
if err := fs.Mkdir("/foo", 0755); err != nil {
if err := fs.Mkdir("/foo", 0o755); err != nil {
t.Fatal(err)
}
@@ -590,13 +590,13 @@ func testFakeFSMkdir(t *testing.T, fs Filesystem) {
t.Fatal(err)
}
if err := fs.Mkdir("/foo", 0755); err == nil {
if err := fs.Mkdir("/foo", 0o755); err == nil {
t.Errorf("got no error while creating existing directory")
}
}
func testFakeFSMkdirInsens(t *testing.T, fs Filesystem) {
if err := fs.Mkdir("/foo", 0755); err != nil {
if err := fs.Mkdir("/foo", 0o755); err != nil {
t.Fatal(err)
}
@@ -604,37 +604,37 @@ func testFakeFSMkdirInsens(t *testing.T, fs Filesystem) {
t.Fatal(err)
}
if err := fs.Mkdir("/FOO", 0755); err == nil {
if err := fs.Mkdir("/FOO", 0o755); err == nil {
t.Errorf("got no error while creating existing directory")
}
}
func testFakeFSOpenFile(t *testing.T, fs Filesystem) {
fd, err := fs.OpenFile("foobar", os.O_RDONLY, 0664)
fd, err := fs.OpenFile("foobar", os.O_RDONLY, 0o664)
if err == nil {
fd.Close()
t.Fatalf("got no error opening a non-existing file")
}
fd, err = fs.OpenFile("foobar", os.O_RDWR|os.O_CREATE, 0664)
fd, err = fs.OpenFile("foobar", os.O_RDWR|os.O_CREATE, 0o664)
if err != nil {
t.Fatal(err)
}
fd.Close()
fd, err = fs.OpenFile("foobar", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0664)
fd, err = fs.OpenFile("foobar", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o664)
if err == nil {
fd.Close()
t.Fatalf("created an existing file while told not to")
}
fd, err = fs.OpenFile("foobar", os.O_RDWR|os.O_CREATE, 0664)
fd, err = fs.OpenFile("foobar", os.O_RDWR|os.O_CREATE, 0o664)
if err != nil {
t.Fatal(err)
}
fd.Close()
fd, err = fs.OpenFile("foobar", os.O_RDWR, 0664)
fd, err = fs.OpenFile("foobar", os.O_RDWR, 0o664)
if err != nil {
t.Fatal(err)
}
@@ -642,31 +642,31 @@ func testFakeFSOpenFile(t *testing.T, fs Filesystem) {
}
func testFakeFSOpenFileInsens(t *testing.T, fs Filesystem) {
fd, err := fs.OpenFile("FooBar", os.O_RDONLY, 0664)
fd, err := fs.OpenFile("FooBar", os.O_RDONLY, 0o664)
if err == nil {
fd.Close()
t.Fatalf("got no error opening a non-existing file")
}
fd, err = fs.OpenFile("fOObar", os.O_RDWR|os.O_CREATE, 0664)
fd, err = fs.OpenFile("fOObar", os.O_RDWR|os.O_CREATE, 0o664)
if err != nil {
t.Fatal(err)
}
fd.Close()
fd, err = fs.OpenFile("fOoBaR", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0664)
fd, err = fs.OpenFile("fOoBaR", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o664)
if err == nil {
fd.Close()
t.Fatalf("created an existing file while told not to")
}
fd, err = fs.OpenFile("FoObAr", os.O_RDWR|os.O_CREATE, 0664)
fd, err = fs.OpenFile("FoObAr", os.O_RDWR|os.O_CREATE, 0o664)
if err != nil {
t.Fatal(err)
}
fd.Close()
fd, err = fs.OpenFile("FOOBAR", os.O_RDWR, 0664)
fd, err = fs.OpenFile("FOOBAR", os.O_RDWR, 0o664)
if err != nil {
t.Fatal(err)
}
@@ -674,7 +674,7 @@ func testFakeFSOpenFileInsens(t *testing.T, fs Filesystem) {
}
func testFakeFSRemoveAll(t *testing.T, fs Filesystem) {
if err := fs.Mkdir("/foo", 0755); err != nil {
if err := fs.Mkdir("/foo", 0o755); err != nil {
t.Fatal(err)
}
@@ -702,7 +702,7 @@ func testFakeFSRemoveAll(t *testing.T, fs Filesystem) {
}
func testFakeFSRemoveAllInsens(t *testing.T, fs Filesystem) {
if err := fs.Mkdir("/Foo", 0755); err != nil {
if err := fs.Mkdir("/Foo", 0o755); err != nil {
t.Fatal(err)
}
@@ -729,7 +729,7 @@ func testFakeFSRemoveAllInsens(t *testing.T, fs Filesystem) {
}
func testFakeFSRemove(t *testing.T, fs Filesystem) {
if err := fs.Mkdir("/Foo", 0755); err != nil {
if err := fs.Mkdir("/Foo", 0o755); err != nil {
t.Fatal(err)
}
@@ -754,7 +754,7 @@ func testFakeFSRemove(t *testing.T, fs Filesystem) {
}
func testFakeFSRemoveInsens(t *testing.T, fs Filesystem) {
if err := fs.Mkdir("/Foo", 0755); err != nil {
if err := fs.Mkdir("/Foo", 0o755); err != nil {
t.Fatal(err)
}
@@ -778,7 +778,7 @@ func testFakeFSRemoveInsens(t *testing.T, fs Filesystem) {
}
func testFakeFSSameFile(t *testing.T, fs Filesystem) {
if err := fs.Mkdir("/Foo", 0755); err != nil {
if err := fs.Mkdir("/Foo", 0o755); err != nil {
t.Fatal(err)
}
@@ -810,7 +810,7 @@ func testFakeFSSameFile(t *testing.T, fs Filesystem) {
}
func testFakeFSSameFileInsens(t *testing.T, fs Filesystem) {
if err := fs.Mkdir("/Foo", 0755); err != nil {
if err := fs.Mkdir("/Foo", 0o755); err != nil {
t.Fatal(err)
}

View File

@@ -104,7 +104,7 @@ func TestCanonicalize(t *testing.T) {
}
func TestFileModeString(t *testing.T) {
var fm FileMode = 0777
var fm FileMode = 0o777
exp := "-rwxrwxrwx"
if fm.String() != exp {
t.Fatalf("Got %v, expected %v", fm.String(), exp)

View File

@@ -23,10 +23,10 @@ func testWalkSkipSymlink(t *testing.T, fsType FilesystemType, uri string) {
fs := NewFilesystem(fsType, uri)
if err := fs.MkdirAll("target/foo", 0755); err != nil {
if err := fs.MkdirAll("target/foo", 0o755); err != nil {
t.Fatal(err)
}
if err := fs.Mkdir("towalk", 0755); err != nil {
if err := fs.Mkdir("towalk", 0o755); err != nil {
t.Fatal(err)
}
if err := fs.CreateSymlink("target", "towalk/symlink"); err != nil {

View File

@@ -7,10 +7,11 @@
package model
import (
"sort"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
"sort"
)
type blockPullReorderer interface {

View File

@@ -14,9 +14,7 @@ import (
"github.com/syncthing/syncthing/lib/protocol"
)
var (
someBlocks = []protocol.BlockInfo{{Offset: 1}, {Offset: 2}, {Offset: 3}}
)
var someBlocks = []protocol.BlockInfo{{Offset: 1}, {Offset: 2}, {Offset: 3}}
func Test_chunk(t *testing.T) {
type args struct {

View File

@@ -10,9 +10,7 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("model", "The root hub")
)
var l = logger.DefaultLogger.NewFacility("model", "The root hub")
func shouldDebug() bool {
return l.ShouldDebug("model")

View File

@@ -33,55 +33,56 @@ func TestDeviceDownloadState(t *testing.T) {
shouldHaveIndexesFrom []protocol.FileDownloadProgressUpdate
shouldNotHaveIndexesFrom []protocol.FileDownloadProgressUpdate
}{
{ //1
{ // 1
[]protocol.FileDownloadProgressUpdate{f1v1p1},
[]protocol.FileDownloadProgressUpdate{f1v1p1},
[]protocol.FileDownloadProgressUpdate{f1v1p2, f1v2p1, f1v2p2},
},
{ //2
{ // 2
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2},
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2},
[]protocol.FileDownloadProgressUpdate{f1v2p1, f1v2p2},
},
{ //3
{ // 3
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v1del},
nil,
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2p1, f1v2p2}},
{ //4
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2p1, f1v2p2},
},
{ // 4
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2del},
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2},
[]protocol.FileDownloadProgressUpdate{f1v2p1, f1v2p2},
},
{ //5
{ // 5
// v2 replaces old v1 data
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2p1},
[]protocol.FileDownloadProgressUpdate{f1v2p1},
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2p2},
},
{ //6
{ // 6
// v1 delete on v2 data does nothing
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2p1, f1v1del},
[]protocol.FileDownloadProgressUpdate{f1v2p1},
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2p2},
},
{ //7
{ // 7
// v2 replacees v1, v2 gets deleted, and v2 part 2 gets added.
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2p1, f1v2del, f1v2p2},
[]protocol.FileDownloadProgressUpdate{f1v2p2},
[]protocol.FileDownloadProgressUpdate{f1v1p1, f1v1p2, f1v2p1},
},
// Multiple files in one go
{ //8
{ // 8
[]protocol.FileDownloadProgressUpdate{f1v1p1, f2v1p1},
[]protocol.FileDownloadProgressUpdate{f1v1p1, f2v1p1},
[]protocol.FileDownloadProgressUpdate{f1v1p2, f2v1p2},
},
{ //9
{ // 9
[]protocol.FileDownloadProgressUpdate{f1v1p1, f2v1p1, f2v1del},
[]protocol.FileDownloadProgressUpdate{f1v1p1},
[]protocol.FileDownloadProgressUpdate{f2v1p1, f2v1p1},
},
{ //10
{ // 10
[]protocol.FileDownloadProgressUpdate{f1v1p1, f2v1del, f2v1p1},
[]protocol.FileDownloadProgressUpdate{f1v1p1, f2v1p1},
[]protocol.FileDownloadProgressUpdate{f1v1p2, f2v1p2},

View File

@@ -398,7 +398,7 @@ func (f *sendReceiveFolder) processNeeded(snap *db.Snapshot, dbUpdateChan chan<-
f.queue.Push(file.Name, file.Size, file.ModTime())
}
case build.IsWindows && file.IsSymlink():
case (build.IsWindows || build.IsAndroid) && file.IsSymlink():
if err := f.handleSymlinkCheckExisting(file, snap, scanChan); err != nil {
f.newPullError(file.Name, fmt.Errorf("handling unsupported symlink: %w", err))
break
@@ -505,13 +505,10 @@ nextFile:
continue nextFile
}
devices := snap.Availability(fileName)
for _, dev := range devices {
if f.model.ConnectedTo(dev) {
// Handle the file normally, by copying and pulling, etc.
f.handleFile(fi, snap, copyChan)
continue nextFile
}
devices := f.model.fileAvailability(f.FolderConfiguration, snap, fi)
if len(devices) > 0 {
f.handleFile(fi, snap, copyChan)
continue
}
f.newPullError(fileName, errNotAvailable)
f.queue.Done(fileName)
@@ -1547,7 +1544,7 @@ func (f *sendReceiveFolder) pullBlock(state pullBlockState, snap *db.Snapshot, o
}
var lastError error
candidates := f.model.availabilityInSnapshot(f.FolderConfiguration, snap, state.file, state.block)
candidates := f.model.blockAvailability(f.FolderConfiguration, snap, state.file, state.block)
loop:
for {
select {

View File

@@ -448,7 +448,7 @@ func (s *indexHandler) receive(fs []protocol.FileInfo, update bool, op string, p
seq := fset.Sequence(deviceID)
// Check that the sequence we get back is what we put in...
if lastSequence > 0 && seq != lastSequence {
if lastSequence > 0 && len(fs) > 0 && seq != lastSequence {
s.logSequenceAnomaly("unexpected sequence after update", map[string]any{
"prevSeq": prevSequence,
"lastSeq": lastSequence,

View File

@@ -2882,16 +2882,31 @@ func (m *model) Availability(folder string, file protocol.FileInfo, block protoc
}
defer snap.Release()
return m.availabilityInSnapshotRLocked(cfg, snap, file, block), nil
return m.blockAvailabilityRLocked(cfg, snap, file, block), nil
}
func (m *model) availabilityInSnapshot(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability {
func (m *model) blockAvailability(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability {
m.mut.RLock()
defer m.mut.RUnlock()
return m.availabilityInSnapshotRLocked(cfg, snap, file, block)
return m.blockAvailabilityRLocked(cfg, snap, file, block)
}
func (m *model) availabilityInSnapshotRLocked(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability {
func (m *model) blockAvailabilityRLocked(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo, block protocol.BlockInfo) []Availability {
var candidates []Availability
candidates = append(candidates, m.fileAvailabilityRLocked(cfg, snap, file)...)
candidates = append(candidates, m.blockAvailabilityFromTemporaryRLocked(cfg, file, block)...)
return candidates
}
func (m *model) fileAvailability(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo) []Availability {
m.mut.RLock()
defer m.mut.RUnlock()
return m.fileAvailabilityRLocked(cfg, snap, file)
}
func (m *model) fileAvailabilityRLocked(cfg config.FolderConfiguration, snap *db.Snapshot, file protocol.FileInfo) []Availability {
var availabilities []Availability
for _, device := range snap.Availability(file.Name) {
if _, ok := m.remoteFolderStates[device]; !ok {
@@ -2905,13 +2920,16 @@ func (m *model) availabilityInSnapshotRLocked(cfg config.FolderConfiguration, sn
availabilities = append(availabilities, Availability{ID: device, FromTemporary: false})
}
}
return availabilities
}
func (m *model) blockAvailabilityFromTemporaryRLocked(cfg config.FolderConfiguration, file protocol.FileInfo, block protocol.BlockInfo) []Availability {
var availabilities []Availability
for _, device := range cfg.Devices {
if m.deviceDownloads[device.DeviceID].Has(cfg.ID, file.Name, file.Version, int(block.Offset/int64(file.BlockSize()))) {
availabilities = append(availabilities, Availability{ID: device.DeviceID, FromTemporary: true})
}
}
return availabilities
}

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("nat", "NAT discovery and port mapping")
)
var l = logger.DefaultLogger.NewFacility("nat", "NAT discovery and port mapping")

View File

@@ -259,7 +259,7 @@ func (s *Service) verifyExistingLocked(ctx context.Context, mapping *Mapping, na
// entry always has the external port.
responseAddrs, err := s.tryNATDevice(ctx, nat, mapping.address, extAddrs[0].Port, leaseTime)
if err != nil {
l.Debugf("Failed to renew %s -> %v open port on %s", mapping, extAddrs, id)
l.Infof("Failed to renew %s -> %v open port on %s: %s", mapping, extAddrs, id, err)
mapping.removeAddressLocked(id)
change = true
continue
@@ -311,7 +311,7 @@ func (s *Service) acquireNewLocked(ctx context.Context, mapping *Mapping, nats m
addrs, err := s.tryNATDevice(ctx, nat, mapping.address, 0, leaseTime)
if err != nil {
l.Debugf("Failed to acquire %s open port on %s", mapping, id)
l.Infof("Failed to acquire %s open port on %s: %s", mapping, id, err)
continue
}
@@ -359,7 +359,7 @@ func (s *Service) tryNATDevice(ctx context.Context, natd Device, intAddr Address
extPort = port
goto findIP
}
l.Debugln("Error extending lease on", natd.ID(), err)
l.Debugf("Error extending lease on %v (external port %d -> internal port %d): %v", natd.ID(), extPort, intAddr.Port, err)
}
for i := 0; i < 10; i++ {
@@ -377,7 +377,8 @@ func (s *Service) tryNATDevice(ctx context.Context, natd Device, intAddr Address
extPort = port
goto findIP
}
l.Debugf("Error getting new lease on %s: %s", natd.ID(), err)
err = fmt.Errorf("getting new lease on %s (external port %d -> internal port %d): %w", natd.ID(), extPort, intAddr.Port, err)
l.Debugf("Error %s", err)
}
return nil, err

View File

@@ -101,7 +101,7 @@ func (w *AtomicWriter) Close() error {
// On Windows, we might not be allowed to rename over the file
// because it's read-only. Get us some write permissions and try
// again.
_ = w.fs.Chmod(w.path, 0644)
_ = w.fs.Chmod(w.path, 0o644)
err = w.fs.Rename(w.next.Name(), w.path)
}
if err != nil {

View File

@@ -17,7 +17,7 @@ func TestCreateAtomicCreate(t *testing.T) {
os.RemoveAll("testdata")
defer os.RemoveAll("testdata")
if err := os.Mkdir("testdata", 0755); err != nil {
if err := os.Mkdir("testdata", 0o755); err != nil {
t.Fatal(err)
}
@@ -52,10 +52,11 @@ func TestCreateAtomicCreate(t *testing.T) {
}
func TestCreateAtomicReplace(t *testing.T) {
testCreateAtomicReplace(t, 0666)
testCreateAtomicReplace(t, 0o666)
}
func TestCreateAtomicReplaceReadOnly(t *testing.T) {
testCreateAtomicReplace(t, 0444) // windows compatible read-only bits
testCreateAtomicReplace(t, 0o444) // windows compatible read-only bits
}
func testCreateAtomicReplace(t *testing.T, oldPerms os.FileMode) {
@@ -66,7 +67,7 @@ func testCreateAtomicReplace(t *testing.T, oldPerms os.FileMode) {
os.RemoveAll(testdir)
if err := os.Mkdir(testdir, 0755); err != nil {
if err := os.Mkdir(testdir, 0o755); err != nil {
t.Fatal(err)
}

View File

@@ -38,7 +38,7 @@ func TestTempFilePermissions(t *testing.T) {
// The temp file should have 0600 permissions at the most, or we have a
// security problem in CreateAtomic.
t.Logf("Got 0%03o", info.Mode())
if info.Mode()&^0600 != 0 {
if info.Mode()&^0o600 != 0 {
t.Errorf("Permission 0%03o is too generous", info.Mode())
}
}

View File

@@ -84,14 +84,14 @@ func Copy(method fs.CopyRangeMethod, src, dst fs.Filesystem, from, to string) (e
func withPreparedTarget(filesystem fs.Filesystem, from, to string, f func() error) error {
// Make sure the destination directory is writeable
toDir := filepath.Dir(to)
if info, err := filesystem.Stat(toDir); err == nil && info.IsDir() && info.Mode()&0200 == 0 {
filesystem.Chmod(toDir, 0755)
if info, err := filesystem.Stat(toDir); err == nil && info.IsDir() && info.Mode()&0o200 == 0 {
filesystem.Chmod(toDir, 0o755)
defer filesystem.Chmod(toDir, info.Mode())
}
// On Windows, make sure the destination file is writeable (or we can't delete it)
if build.IsWindows {
filesystem.Chmod(to, 0666)
filesystem.Chmod(to, 0o666)
if !strings.EqualFold(from, to) {
err := filesystem.Remove(to)
if err != nil && !fs.IsNotExist(err) {

View File

@@ -16,8 +16,10 @@ import (
"github.com/syncthing/syncthing/lib/fs"
)
var rand uint32
var randmu sync.Mutex
var (
rand uint32
randmu sync.Mutex
)
func reseed() uint32 {
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
@@ -48,7 +50,7 @@ func TempFile(filesystem fs.Filesystem, dir, prefix string) (f fs.File, err erro
nconflict := 0
for i := 0; i < 10000; i++ {
name := filepath.Join(dir, prefix+nextSuffix())
f, err = filesystem.OpenFile(name, fs.OptReadWrite|fs.OptCreate|fs.OptExclusive, 0600)
f, err = filesystem.OpenFile(name, fs.OptReadWrite|fs.OptCreate|fs.OptExclusive, 0o600)
if fs.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("pmp", "NAT-PMP discovery and port mapping")
)
var l = logger.DefaultLogger.NewFacility("pmp", "NAT-PMP discovery and port mapping")

View File

@@ -317,10 +317,10 @@ func PermsEqual(a, b uint32) bool {
if build.IsWindows {
// There is only writeable and read only, represented for user, group
// and other equally. We only compare against user.
return a&0600 == b&0600
return a&0o600 == b&0o600
}
// All bits count
return a&0777 == b&0777
return a&0o777 == b&0o777
}
// BlocksEqual returns true when the two files have identical block lists.

View File

@@ -6,6 +6,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("protocol", "The BEP protocol")
)
var l = logger.DefaultLogger.NewFacility("protocol", "The BEP protocol")

View File

@@ -4,19 +4,21 @@ package protocol
import "testing"
var formatted = "P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"
var formatCases = []string{
"P56IOI-7MZJNU-2IQGDR-EYDM2M-GTMGL3-BXNPQ6-W5BTBB-Z4TJXZ-WICQ",
"P56IOI-7MZJNU2Y-IQGDR-EYDM2M-GTI-MGL3-BXNPQ6-W5BM-TBB-Z4TJXZ-WICQ2",
"P56IOI7 MZJNU2I QGDREYD M2MGTMGL 3BXNPQ6W 5BTB BZ4T JXZWICQ",
"P56IOI7 MZJNU2Y IQGDREY DM2MGTI MGL3BXN PQ6W5BM TBBZ4TJ XZWICQ2",
"P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ",
"p56ioi7mzjnu2iqgdreydm2mgtmgl3bxnpq6w5btbbz4tjxzwicq",
"P56IOI7MZJNU2YIQGDREYDM2MGTIMGL3BXNPQ6W5BMTBBZ4TJXZWICQ2",
"P561017MZJNU2YIQGDREYDM2MGTIMGL3BXNPQ6W5BMT88Z4TJXZWICQ2",
"p56ioi7mzjnu2yiqgdreydm2mgtimgl3bxnpq6w5bmtbbz4tjxzwicq2",
"p561017mzjnu2yiqgdreydm2mgtimgl3bxnpq6w5bmt88z4tjxzwicq2",
}
var (
formatted = "P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"
formatCases = []string{
"P56IOI-7MZJNU-2IQGDR-EYDM2M-GTMGL3-BXNPQ6-W5BTBB-Z4TJXZ-WICQ",
"P56IOI-7MZJNU2Y-IQGDR-EYDM2M-GTI-MGL3-BXNPQ6-W5BM-TBB-Z4TJXZ-WICQ2",
"P56IOI7 MZJNU2I QGDREYD M2MGTMGL 3BXNPQ6W 5BTB BZ4T JXZWICQ",
"P56IOI7 MZJNU2Y IQGDREY DM2MGTI MGL3BXN PQ6W5BM TBBZ4TJ XZWICQ2",
"P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ",
"p56ioi7mzjnu2iqgdreydm2mgtmgl3bxnpq6w5btbbz4tjxzwicq",
"P56IOI7MZJNU2YIQGDREYDM2MGTIMGL3BXNPQ6W5BMTBBZ4TJXZWICQ2",
"P561017MZJNU2YIQGDREYDM2MGTIMGL3BXNPQ6W5BMT88Z4TJXZWICQ2",
"p56ioi7mzjnu2yiqgdreydm2mgtimgl3bxnpq6w5bmtbbz4tjxzwicq2",
"p561017mzjnu2yiqgdreydm2mgtimgl3bxnpq6w5bmt88z4tjxzwicq2",
}
)
func TestFormatDeviceID(t *testing.T) {
for i, tc := range formatCases {

View File

@@ -212,38 +212,44 @@ func (e encryptedConnection) Request(ctx context.Context, req *Request) ([]byte,
if !ok {
return e.conn.Request(ctx, req)
}
fileKey := e.keyGen.FileKey(req.Name, folderKey)
// Encrypt / adjust the request parameters.
origSize := req.Size
origName := req.Name
if req.Size < minPaddedSize {
encSize := req.Size
if encSize < minPaddedSize {
// Make a request for minPaddedSize data instead of the smaller
// block. We'll chop of the extra data later.
req.Size = minPaddedSize
encSize = minPaddedSize
}
encSize += blockOverhead
encName := encryptName(req.Name, folderKey)
encOffset := req.Offset + int64(req.BlockNo*blockOverhead)
encSize := req.Size + blockOverhead
encHash := encryptBlockHash(req.Hash, req.Offset, fileKey)
// Perform that request, getting back an encrypted block.
req.Name = encName
req.Offset = encOffset
req.Size = encSize
bs, err := e.conn.Request(ctx, req)
encReq := &Request{
ID: req.ID,
Folder: req.Folder,
Name: encName,
Offset: encOffset,
Size: encSize,
Hash: encHash,
BlockNo: req.BlockNo,
}
bs, err := e.conn.Request(ctx, encReq)
if err != nil {
return nil, err
}
// Return the decrypted block (or an error if it fails decryption)
fileKey := e.keyGen.FileKey(origName, folderKey)
bs, err = DecryptBytes(bs, fileKey)
if err != nil {
return nil, err
}
return bs[:origSize], nil
return bs[:req.Size], nil
}
func (e encryptedConnection) DownloadProgress(ctx context.Context, dp *DownloadProgress) {
@@ -327,15 +333,7 @@ func encryptFileInfo(keyGen *KeyGenerator, fi FileInfo, folderKey *[keySize]byte
b.Size = minPaddedSize
}
size := b.Size + blockOverhead
// The offset goes into the encrypted block hash as additional data,
// essentially mixing in with the nonce. This means a block hash
// remains stable for the same data at the same offset, but doesn't
// reveal the existence of identical data blocks at other offsets.
var additional [8]byte
binary.BigEndian.PutUint64(additional[:], uint64(b.Offset))
hash := encryptDeterministic(b.Hash, fileKey, additional[:])
hash := encryptBlockHash(b.Hash, b.Offset, fileKey)
blocks[i] = BlockInfo{
Hash: hash,
Offset: offset,
@@ -374,6 +372,16 @@ func encryptFileInfo(keyGen *KeyGenerator, fi FileInfo, folderKey *[keySize]byte
return enc
}
func encryptBlockHash(hash []byte, offset int64, fileKey *[keySize]byte) []byte {
// The offset goes into the encrypted block hash as additional data,
// essentially mixing in with the nonce. This means a block hash
// remains stable for the same data at the same offset, but doesn't
// reveal the existence of identical data blocks at other offsets.
var additional [8]byte
binary.BigEndian.PutUint64(additional[:], uint64(offset))
return encryptDeterministic(hash, fileKey, additional[:])
}
func decryptFileInfos(keyGen *KeyGenerator, files []FileInfo, folderKey *[keySize]byte) error {
for i, fi := range files {
decFI, err := DecryptFileInfo(keyGen, fi, folderKey)

View File

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

View File

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

View File

@@ -29,9 +29,11 @@ type header struct {
messageLength int32
}
type Ping struct{}
type Pong struct{}
type RelayFull struct{}
type (
Ping struct{}
Pong struct{}
RelayFull struct{}
)
type JoinRelayRequest struct {
Token string

View File

@@ -60,6 +60,7 @@ func (o *header) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *header) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.magic = u.UnmarshalUint32()
o.messageType = int32(u.UnmarshalUint32())
@@ -81,6 +82,7 @@ struct Ping {
func (Ping) XDRSize() int {
return 0
}
func (Ping) MarshalXDR() ([]byte, error) {
return nil, nil
}
@@ -115,6 +117,7 @@ struct Pong {
func (Pong) XDRSize() int {
return 0
}
func (Pong) MarshalXDR() ([]byte, error) {
return nil, nil
}
@@ -149,6 +152,7 @@ struct RelayFull {
func (RelayFull) XDRSize() int {
return 0
}
func (RelayFull) MarshalXDR() ([]byte, error) {
return nil, nil
}
@@ -215,6 +219,7 @@ func (o *JoinRelayRequest) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *JoinRelayRequest) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.Token = u.UnmarshalString()
return u.Error
@@ -269,6 +274,7 @@ func (o *JoinSessionRequest) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *JoinSessionRequest) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.Key = u.UnmarshalBytesMax(32)
return u.Error
@@ -325,6 +331,7 @@ func (o *Response) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *Response) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.Code = int32(u.UnmarshalUint32())
o.Message = u.UnmarshalString()
@@ -380,6 +387,7 @@ func (o *ConnectRequest) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *ConnectRequest) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.ID = u.UnmarshalBytesMax(32)
return u.Error
@@ -462,6 +470,7 @@ func (o *SessionInvitation) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *SessionInvitation) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
o.From = u.UnmarshalBytesMax(32)
o.Key = u.UnmarshalBytesMax(32)

View File

@@ -27,43 +27,67 @@ var blocksTestData = []struct {
hash []string
weakhash []uint32
}{
{[]byte(""), 1024, []string{
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
{
[]byte(""), 1024,
[]string{
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
},
[]uint32{0},
},
{[]byte("contents"), 1024, []string{
"d1b2a59fbea7e20077af9f91b27e95e865061b270be03ff539ab3b73587882e8"},
{
[]byte("contents"), 1024,
[]string{
"d1b2a59fbea7e20077af9f91b27e95e865061b270be03ff539ab3b73587882e8",
},
[]uint32{0x0f3a036f},
},
{[]byte("contents"), 9, []string{
"d1b2a59fbea7e20077af9f91b27e95e865061b270be03ff539ab3b73587882e8"},
{
[]byte("contents"), 9,
[]string{
"d1b2a59fbea7e20077af9f91b27e95e865061b270be03ff539ab3b73587882e8",
},
[]uint32{0x0f3a036f},
},
{[]byte("contents"), 8, []string{
"d1b2a59fbea7e20077af9f91b27e95e865061b270be03ff539ab3b73587882e8"},
{
[]byte("contents"), 8,
[]string{
"d1b2a59fbea7e20077af9f91b27e95e865061b270be03ff539ab3b73587882e8",
},
[]uint32{0x0f3a036f},
},
{[]byte("contents"), 7, []string{
"ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73",
"043a718774c572bd8a25adbeb1bfcd5c0256ae11cecf9f9c3f925d0e52beaf89"},
{
[]byte("contents"), 7,
[]string{
"ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73",
"043a718774c572bd8a25adbeb1bfcd5c0256ae11cecf9f9c3f925d0e52beaf89",
},
[]uint32{0x0bcb02fc, 0x00740074},
},
{[]byte("contents"), 3, []string{
"1143da2bc54c495c4be31d3868785d39ffdfd56df5668f0645d8f14d47647952",
"e4432baa90819aaef51d2a7f8e148bf7e679610f3173752fabb4dcb2d0f418d3",
"44ad63f60af0f6db6fdde6d5186ef78176367df261fa06be3079b6c80c8adba4"},
{
[]byte("contents"), 3,
[]string{
"1143da2bc54c495c4be31d3868785d39ffdfd56df5668f0645d8f14d47647952",
"e4432baa90819aaef51d2a7f8e148bf7e679610f3173752fabb4dcb2d0f418d3",
"44ad63f60af0f6db6fdde6d5186ef78176367df261fa06be3079b6c80c8adba4",
},
[]uint32{0x02780141, 0x02970148, 0x015d00e8},
},
{[]byte("conconts"), 3, []string{
"1143da2bc54c495c4be31d3868785d39ffdfd56df5668f0645d8f14d47647952",
"1143da2bc54c495c4be31d3868785d39ffdfd56df5668f0645d8f14d47647952",
"44ad63f60af0f6db6fdde6d5186ef78176367df261fa06be3079b6c80c8adba4"},
{
[]byte("conconts"), 3,
[]string{
"1143da2bc54c495c4be31d3868785d39ffdfd56df5668f0645d8f14d47647952",
"1143da2bc54c495c4be31d3868785d39ffdfd56df5668f0645d8f14d47647952",
"44ad63f60af0f6db6fdde6d5186ef78176367df261fa06be3079b6c80c8adba4",
},
[]uint32{0x02780141, 0x02780141, 0x015d00e8},
},
{[]byte("contenten"), 3, []string{
"1143da2bc54c495c4be31d3868785d39ffdfd56df5668f0645d8f14d47647952",
"e4432baa90819aaef51d2a7f8e148bf7e679610f3173752fabb4dcb2d0f418d3",
"e4432baa90819aaef51d2a7f8e148bf7e679610f3173752fabb4dcb2d0f418d3"},
{
[]byte("contenten"), 3,
[]string{
"1143da2bc54c495c4be31d3868785d39ffdfd56df5668f0645d8f14d47647952",
"e4432baa90819aaef51d2a7f8e148bf7e679610f3173752fabb4dcb2d0f418d3",
"e4432baa90819aaef51d2a7f8e148bf7e679610f3173752fabb4dcb2d0f418d3",
},
[]uint32{0x02780141, 0x02970148, 0x02970148},
},
}
@@ -72,7 +96,6 @@ func TestBlocks(t *testing.T) {
for testNo, test := range blocksTestData {
buf := bytes.NewBuffer(test.data)
blocks, err := Blocks(context.TODO(), buf, test.blocksize, -1, nil, true)
if err != nil {
t.Fatal(err)
}

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("scanner", "File change detection and hashing")
)
var l = logger.DefaultLogger.NewFacility("scanner", "File change detection and hashing")

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("stats", "Persistent device and folder statistics")
)
var l = logger.DefaultLogger.NewFacility("stats", "Persistent device and folder statistics")

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("stun", "STUN functionality")
)
var l = logger.DefaultLogger.NewFacility("stun", "STUN functionality")

View File

@@ -10,9 +10,7 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("app", "Main run facility")
)
var l = logger.DefaultLogger.NewFacility("app", "Main run facility")
func shouldDebug() bool {
return l.ShouldDebug("app")

View File

@@ -33,7 +33,7 @@ func EnsureDir(dir string, mode fs.FileMode) error {
// Apparently the stat may fail even though the mkdirall passed. If it
// does, we'll just assume things are in order and let other things
// fail (like loading or creating the config...).
currentMode := fi.Mode() & 0777
currentMode := fi.Mode() & 0o777
if currentMode != mode {
err := fs.Chmod(".", mode)
// This can fail on crappy filesystems, nothing we can do about it.
@@ -63,6 +63,8 @@ func DefaultConfig(path string, myID protocol.DeviceID, evLogger events.Logger,
if skipPortProbing {
l.Infoln("Using default network port numbers instead of probing for free ports")
// Record address override initially
newCfg.GUI.RawAddress = newCfg.GUI.Address()
} else if err := newCfg.ProbeFreePorts(); err != nil {
return nil, err
}
@@ -139,7 +141,7 @@ func copyFile(src, dst string) error {
return err
}
if err := os.WriteFile(dst, bs, 0600); err != nil {
if err := os.WriteFile(dst, bs, 0o600); err != nil {
// Attempt to clean up
os.Remove(dst)
return err

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("upgrade", "Binary upgrades")
)
var l = logger.DefaultLogger.NewFacility("upgrade", "Binary upgrades")

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("upnp", "UPnP discovery and port mapping")
)
var l = logger.DefaultLogger.NewFacility("upnp", "UPnP discovery and port mapping")

View File

@@ -206,7 +206,7 @@ func (s *IGDService) AddPortMapping(ctx context.Context, protocol nat.Protocol,
}
err = fmt.Errorf("UPnP Error: %s (%d)", envelope.ErrorDescription, envelope.ErrorCode)
l.Infof("Couldn't add port mapping for %s (external port %d -> internal port %d/%s): %s", s.LocalIPv4, externalPort, internalPort, protocol, err)
l.Debugf("Couldn't add port mapping for %s (external port %d -> internal port %d/%s): %s", s.LocalIPv4, externalPort, internalPort, protocol, err)
}
return externalPort, err

View File

@@ -210,7 +210,6 @@ USER-AGENT: syncthing/%s
proto = "udp6"
}
socket, err := net.ListenMulticastUDP(proto, intf, &net.UDPAddr{IP: ssdp.IP})
if err != nil {
if runtime.GOOS == "windows" && ip6 {
// Requires https://github.com/golang/go/issues/63529 to be fixed.
@@ -257,7 +256,7 @@ loop:
if e, ok := err.(net.Error); ok && e.Timeout() {
continue // continue reading
}
l.Infoln("UPnP read:", err) //legitimate error, not a timeout.
l.Infoln("UPnP read:", err) // legitimate error, not a timeout.
break
}
@@ -411,7 +410,6 @@ func localIPv4Fallback(ctx context.Context, url *url.URL) (net.IP, error) {
defer cancel()
conn, err := dialer.DialContext(timeoutCtx, "udp4", url.Host)
if err != nil {
return nil, err
}

View File

@@ -13,8 +13,7 @@ import (
)
func TestExternalIPParsing(t *testing.T) {
soapResponse :=
[]byte(`<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
soapResponse := []byte(`<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:GetExternalIPAddressResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
<NewExternalIPAddress>1.2.3.4</NewExternalIPAddress>
@@ -34,8 +33,7 @@ func TestExternalIPParsing(t *testing.T) {
}
func TestSoapFaultParsing(t *testing.T) {
soapResponse :=
[]byte(`<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
soapResponse := []byte(`<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("ur", "Usage reporting")
)
var l = logger.DefaultLogger.NewFacility("ur", "Usage reporting")

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("versioner", "File versioning")
)
var l = logger.DefaultLogger.NewFacility("versioner", "File versioning")

View File

@@ -27,7 +27,7 @@ import (
// └── remove21
// └── remove22
func TestEmptyDirs(t *testing.T) {
var paths = []struct {
paths := []struct {
path string
isFile bool
}{
@@ -44,7 +44,7 @@ func TestEmptyDirs(t *testing.T) {
{"remove2/remove21/remove22", false},
}
var expected = []string{
expected := []string{
"remove2/remove21/remove22",
"remove2/remove21",
"remove2",

View File

@@ -81,10 +81,10 @@ func prepForRemoval(t *testing.T, file string) {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {
if err := os.MkdirAll(filepath.Dir(file), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(file, []byte("hello\n"), 0644); err != nil {
if err := os.WriteFile(file, []byte("hello\n"), 0o644); err != nil {
t.Fatal(err)
}
}

View File

@@ -30,7 +30,7 @@ type simple struct {
}
func newSimple(cfg config.FolderConfiguration) Versioner {
var keep, err = strconv.Atoi(cfg.Versioning.Params["keep"])
keep, err := strconv.Atoi(cfg.Versioning.Params["keep"])
cleanoutDays, _ := strconv.Atoi(cfg.Versioning.Params["cleanoutDays"])
// On error we default to 0, "do not clean out the versioned items"

View File

@@ -134,7 +134,7 @@ func TestCreateVersionPath(t *testing.T) {
// Create a test dir and file
tmpDir := t.TempDir()
if err := os.WriteFile(filepath.Join(tmpDir, archiveFile), []byte("sup"), 0644); err != nil {
if err := os.WriteFile(filepath.Join(tmpDir, archiveFile), []byte("sup"), 0o644); err != nil {
t.Fatal(err)
}

View File

@@ -182,7 +182,7 @@ func readFile(t *testing.T, filesystem fs.Filesystem, name string) string {
}
func writeFile(t *testing.T, filesystem fs.Filesystem, name, content string) {
fd, err := filesystem.OpenFile(name, fs.OptReadWrite|fs.OptCreate, 0777)
fd, err := filesystem.OpenFile(name, fs.OptReadWrite|fs.OptCreate, 0o777)
if err != nil {
t.Fatal(err)
}
@@ -213,7 +213,7 @@ func TestTrashcanCleanOut(t *testing.T) {
v := newTrashcan(cfg)
var testcases = map[string]bool{
testcases := map[string]bool{
".stversions/file1": false,
".stversions/file2": true,
".stversions/keep1/file1": false,
@@ -229,7 +229,7 @@ func TestTrashcanCleanOut(t *testing.T) {
t.Run("trashcan versioner trashcan clean up", func(t *testing.T) {
oldTime := time.Now().Add(-8 * 24 * time.Hour)
for file, shouldRemove := range testcases {
fs.MkdirAll(filepath.Dir(file), 0777)
fs.MkdirAll(filepath.Dir(file), 0o777)
writeFile(t, fs, file, "some content")

View File

@@ -10,6 +10,4 @@ import (
"github.com/syncthing/syncthing/lib/logger"
)
var (
l = logger.DefaultLogger.NewFacility("watchaggregator", "Filesystem event watcher")
)
var l = logger.DefaultLogger.NewFacility("watchaggregator", "Filesystem event watcher")

View File

@@ -23,8 +23,10 @@ import (
"github.com/chmduquesne/rollinghash/buzhash64"
)
const testFile = "../model/testdata/tmpfile"
const size = 128 << 10
const (
testFile = "../model/testdata/tmpfile"
size = 128 << 10
)
func BenchmarkFind1MFile(b *testing.B) {
b.ReportAllocs()
@@ -96,7 +98,6 @@ func BenchmarkBlock(b *testing.B) {
bbb.SetBytes(testSize)
bbb.ReportAllocs()
})
})
}
}
@@ -144,7 +145,6 @@ func BenchmarkRoll(b *testing.B) {
bbb.SetBytes(testSize)
bbb.ReportAllocs()
})
})
}
}

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "STDISCOSRV" "1" "Sep 13, 2024" "v1.27.11" "Syncthing"
.TH "STDISCOSRV" "1" "Oct 23, 2024" "v1.28.0" "Syncthing"
.SH NAME
stdiscosrv \- Syncthing Discovery Server
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "STRELAYSRV" "1" "Sep 13, 2024" "v1.27.11" "Syncthing"
.TH "STRELAYSRV" "1" "Oct 23, 2024" "v1.28.0" "Syncthing"
.SH NAME
strelaysrv \- Syncthing Relay Server
.SH SYNOPSIS

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