Compare commits

..
Author SHA1 Message Date
Jakob Borg 0945304a79 build: fix detection of next rc version 2025-06-20 11:17:23 +02:00
Jakob Borg 9703dd9f57 build: import release workflow changes from main 2025-06-20 11:12:05 +02:00
yparitcherandJakob Borg 259e9ef08e fix(protocol): slightly loosen/correct ownership comparison criteria (fixes #9879) (#10176)
Only Require either matching UID & GID OR matching Names.

If the 2 devices have a different Name => UID mapping, they can never be
totaly equal. Therefore when syncing we try matching the Name and fall
back to the UID. However when scanning for changes we currently require
both the Name & UID to match. This leads to forever having out of sync
files back and forth, or local additions when receive only.

This patch does not change the sending behavoir. It only change what we
decide is equal for exisiting files with mismapped Name => UID,

The added testcases show the change: Test 1,5,6 are the same as current.
Test 2,3 Are what change with this patch (from false to true). Test 4 is
a subset of test 2 they is currently special cased as true, which does
not chnage.

Co-authored-by: Jakob Borg <jakob@kastelo.net>
2025-06-20 09:55:42 +02:00
Simon Frei 6a0c6128d8 fix(watchaggregator): properly handle sub-second watch durations (fixes #9927) (#10179)
I'll let Audrius words from the ticket explain this :)

> I'm a bit lost, time.Duration is an int64, yet watcher delay is float,
> anything sub 1s gets rounded down to 0, so you just end up going into
an
> infinite loop.


https://github.com/syncthing/syncthing/issues/9927#issuecomment-2967736106
2025-06-15 10:29:33 +02:00
550 changed files with 62328 additions and 17228 deletions
-52
View File
@@ -1,52 +0,0 @@
version: 1
creds:
- registry: docker.io
user: "{{env \"DOCKERHUB_USERNAME\"}}"
pass: "{{env \"DOCKERHUB_TOKEN\"}}"
defaults:
ratelimit:
min: 100
retry: 1m
parallel: 4
sync:
- source: ghcr.io/syncthing/syncthing
target: docker.io/syncthing/syncthing
type: repository
tags:
allow:
- latest
- rc
- edge
- \d+
- \d+\.\d+
- \d+\.\d+\.\d+
- \d+\.\d+\.\d+-rc\.\d+
- source: ghcr.io/syncthing/relaysrv
target: docker.io/syncthing/relaysrv
type: repository
tags:
allow:
- latest
- rc
- edge
- \d+
- \d+\.\d+
- \d+\.\d+\.\d+
- \d+\.\d+\.\d+-rc\.\d+
- source: ghcr.io/syncthing/discosrv
target: docker.io/syncthing/discosrv
type: repository
tags:
allow:
- latest
- rc
- edge
- \d+
- \d+\.\d+
- \d+\.\d+\.\d+
- \d+\.\d+\.\d+-rc\.\d+
+1 -1
View File
@@ -7,7 +7,7 @@ on:
- infra-* - infra-*
env: env:
GO_VERSION: "~1.25.0" GO_VERSION: "~1.24.0"
CGO_ENABLED: "0" CGO_ENABLED: "0"
BUILD_USER: docker BUILD_USER: docker
BUILD_HOST: github.syncthing.net BUILD_HOST: github.syncthing.net
+205 -297
View File
@@ -13,11 +13,12 @@ env:
# The go version to use for builds. We set check-latest to true when # The go version to use for builds. We set check-latest to true when
# installing, so we get the latest patch version that matches the # installing, so we get the latest patch version that matches the
# expression. # expression.
GO_VERSION: "~1.25.0" GO_VERSION: "~1.24.0"
# Optimize compatibility on the slow architectures. # Optimize compatibility on the slow archictures.
GO386: softfloat
GOARM: "5"
GOMIPS: softfloat GOMIPS: softfloat
GOARM: "6"
# Avoid hilarious amounts of obscuring log output when running tests. # Avoid hilarious amounts of obscuring log output when running tests.
LOGGER_DISCARD: "1" LOGGER_DISCARD: "1"
@@ -26,9 +27,6 @@ env:
BUILD_USER: builder BUILD_USER: builder
BUILD_HOST: github.syncthing.net BUILD_HOST: github.syncthing.net
TAGS: "sqlite_omit_load_extension sqlite_dbstat"
TAGS_LINUX: "sqlite_omit_load_extension sqlite_dbstat netgo osusergo"
# A note on actions and third party code... The actions under actions/ (like # A note on actions and third party code... The actions under actions/ (like
# `uses: actions/checkout`) are maintained by GitHub, and we need to trust # `uses: actions/checkout`) are maintained by GitHub, and we need to trust
# GitHub to maintain their code and infrastructure or we're in deep shit in # GitHub to maintain their code and infrastructure or we're in deep shit in
@@ -38,58 +36,6 @@ env:
jobs: jobs:
#
# Source
#
facts:
name: Gather common facts
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get-version.outputs.version }}
release-kind: ${{ steps.get-version.outputs.release-kind }}
release-generation: ${{ steps.get-version.outputs.release-generation }}
go-version: ${{ steps.get-go.outputs.go-version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
check-latest: true
- name: Get Syncthing version
id: get-version
run: |
version=$(go run build.go version)
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "Version: $version"
kind=stable
if [[ $version == *-rc.[0-9] || $version == *-rc.[0-9][0-9] ]] ; then
kind=candidate
elif [[ $version == *-* ]] ; then
kind=nightly
fi
echo "release-kind=$kind" >> "$GITHUB_OUTPUT"
echo "Release kind: $kind"
generation=v1
if [[ $version == v2.* ]] ; then
generation=v2
fi
echo "release-generation=$generation" >> "$GITHUB_OUTPUT"
echo "Release generation: $generation"
- name: Get Go version
id: get-go
run: |
go version
echo "go-version=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_OUTPUT
# #
# Tests for all platforms. Runs a matrix build on Windows, Linux and Mac, # Tests for all platforms. Runs a matrix build on Windows, Linux and Mac,
# with the list of expected supported Go versions (current, previous). # with the list of expected supported Go versions (current, previous).
@@ -103,7 +49,7 @@ jobs:
runner: ["windows-latest", "ubuntu-latest", "macos-latest"] runner: ["windows-latest", "ubuntu-latest", "macos-latest"]
# The oldest version in this list should match what we have in our go.mod. # The oldest version in this list should match what we have in our go.mod.
# Variables don't seem to be supported here, or we could have done something nice. # Variables don't seem to be supported here, or we could have done something nice.
go: ["~1.24.0", "~1.25.0"] go: ["~1.23.0", "~1.24.0"]
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
steps: steps:
- name: Set git to use LF - name: Set git to use LF
@@ -142,7 +88,6 @@ jobs:
LOKI_USER: ${{ secrets.LOKI_USER }} LOKI_USER: ${{ secrets.LOKI_USER }}
LOKI_PASSWORD: ${{ secrets.LOKI_PASSWORD }} LOKI_PASSWORD: ${{ secrets.LOKI_PASSWORD }}
LOKI_LABELS: "go=${{ matrix.go }},runner=${{ matrix.runner }},repo=${{ github.repository }},ref=${{ github.ref }}" LOKI_LABELS: "go=${{ matrix.go }},runner=${{ matrix.runner }},repo=${{ github.repository }},ref=${{ github.ref }}"
CGO_ENABLED: "1"
# #
# The basic checks job is a virtual one that depends on the matrix tests, # The basic checks job is a virtual one that depends on the matrix tests,
@@ -164,8 +109,6 @@ jobs:
- package-debian - package-debian
- package-windows - package-windows
- govulncheck - govulncheck
- golangci
- meta
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -175,28 +118,39 @@ jobs:
package-windows: package-windows:
name: Package for Windows name: Package for Windows
runs-on: ubuntu-latest runs-on: windows-latest
needs:
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
steps: steps:
- name: Set git to use LF
# Without this, the checkout will happen with CRLF line endings,
# which is fine for the source code but messes up tests that depend
# on data on disk being as expected. Ideally, those tests should be
# fixed, but not today.
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- uses: mlugg/setup-zig@v2 - name: Get actual Go version
run: |
go version
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: | path: |
~/.cache/go-build ~\AppData\Local\go-build
~/go/pkg/mod ~\go\pkg\mod
key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-package-windows-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-package-${{ hashFiles('**/go.sum') }}
- name: Install dependencies - name: Install dependencies
run: | run: |
@@ -204,14 +158,15 @@ jobs:
- name: Create packages - name: Create packages
run: | run: |
for tgt in syncthing stdiscosrv strelaysrv ; do $targets = 'syncthing', 'stdiscosrv', 'strelaysrv'
go run build.go -tags "${{env.TAGS}}" -goos windows -goarch amd64 -cc "zig cc -target x86_64-windows" zip $tgt $archs = 'amd64', 'arm', 'arm64', '386'
go run build.go -tags "${{env.TAGS}}" -goos windows -goarch 386 -cc "zig cc -target x86-windows" zip $tgt foreach ($arch in $archs) {
go run build.go -tags "${{env.TAGS}}" -goos windows -goarch arm64 -cc "zig cc -target aarch64-windows" zip $tgt foreach ($tgt in $targets) {
# go run build.go -tags "${{env.TAGS}}" -goos windows -goarch arm -cc "zig cc -target thumb-windows" zip $tgt # fails with linker errors go run build.go -goarch $arch zip $tgt
done }
}
env: env:
CGO_ENABLED: "1" CGO_ENABLED: "0"
- name: Archive artifacts - name: Archive artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -219,15 +174,9 @@ jobs:
name: unsigned-packages-windows name: unsigned-packages-windows
path: "*.zip" path: "*.zip"
#
# Codesign binaries for Windows. This job runs only when called in the
# Syncthing repo for release branches and tags, as it requires our
# specific code signing keys etc.
#
codesign-windows: codesign-windows:
name: Codesign for Windows name: Codesign for Windows
if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
environment: release environment: release
runs-on: windows-latest runs-on: windows-latest
needs: needs:
@@ -285,49 +234,40 @@ jobs:
package-linux: package-linux:
name: Package for Linux name: Package for Linux
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- uses: mlugg/setup-zig@v2 - name: Get actual Go version
run: |
go version
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-package-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-package-${{ hashFiles('**/go.sum') }}
- name: Create packages - name: Create packages
run: | run: |
sudo apt-get install -y gcc-mips64-linux-gnuabi64 gcc-mips64el-linux-gnuabi64 archs=$(go tool dist list | grep linux | sed 's#linux/##')
for goarch in $archs ; do
for tgt in syncthing stdiscosrv strelaysrv ; do for tgt in syncthing stdiscosrv strelaysrv ; do
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch amd64 -cc "zig cc -target x86_64-linux-musl" tar "$tgt" go run build.go -goarch "$goarch" tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch 386 -cc "zig cc -target x86-linux-musl" tar "$tgt" done
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch arm -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch arm64 -cc "zig cc -target aarch64-linux-musl" tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch mips -cc "zig cc -target mips-linux-musleabi" tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch mipsle -cc "zig cc -target mipsel-linux-musleabi" tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch mips64 -cc mips64-linux-gnuabi64-gcc tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch mips64le -cc mips64el-linux-gnuabi64-gcc tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch riscv64 -cc "zig cc -target riscv64-linux-musl" tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch s390x -cc "zig cc -target s390x-linux-musl" tar "$tgt"
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch loong64 -cc "zig cc -target loongarch64-linux-musl" tar "$tgt"
# go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch ppc64 -cc "zig cc -target powerpc64-linux-musl" tar "$tgt" # fails with linkmode not supported
go run build.go -tags "${{env.TAGS_LINUX}}" -goos linux -goarch ppc64le -cc "zig cc -target powerpc64le-linux-musl" tar "$tgt"
done done
env: env:
CGO_ENABLED: "1" CGO_ENABLED: "0"
EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
- name: Archive artifacts - name: Archive artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -338,39 +278,39 @@ jobs:
compat.json compat.json
# #
# macOS. The entire build runs in the release environment because code # macOS
# signing is part of the build process, so it is limited to release
# branches on the Syncthing repo.
# #
package-macos: package-macos:
name: Package for macOS name: Package for macOS
if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
environment: release environment: release
runs-on: macos-latest runs-on: macos-latest
needs:
- facts
env:
CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY }}
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- name: Get actual Go version
run: |
go version
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-package-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-package-${{ hashFiles('**/go.sum') }}
- name: Import signing certificate - name: Import signing certificate
if: env.CODESIGN_IDENTITY != ''
run: | run: |
# Set up a run-specific keychain, making it available for the # Set up a run-specific keychain, making it available for the
# `codesign` tool. # `codesign` tool.
@@ -398,7 +338,7 @@ jobs:
- name: Create package (amd64) - name: Create package (amd64)
run: | run: |
for tgt in syncthing stdiscosrv strelaysrv ; do for tgt in syncthing stdiscosrv strelaysrv ; do
go run build.go -tags "${{env.TAGS}}" -goarch amd64 zip "$tgt" go run build.go -goarch amd64 zip "$tgt"
done done
env: env:
CGO_ENABLED: "1" CGO_ENABLED: "1"
@@ -414,7 +354,7 @@ jobs:
EOT EOT
chmod 755 xgo.sh chmod 755 xgo.sh
for tgt in syncthing stdiscosrv strelaysrv ; do for tgt in syncthing stdiscosrv strelaysrv ; do
go run build.go -tags "${{env.TAGS}}" -gocmd ./xgo.sh -goarch arm64 zip "$tgt" go run build.go -gocmd ./xgo.sh -goarch arm64 zip "$tgt"
done done
env: env:
CGO_ENABLED: "1" CGO_ENABLED: "1"
@@ -443,7 +383,7 @@ jobs:
notarize-macos: notarize-macos:
name: Notarize for macOS name: Notarize for macOS
if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
environment: release environment: release
needs: needs:
- package-macos - package-macos
@@ -477,25 +417,29 @@ jobs:
package-cross: package-cross:
name: Package cross compiled name: Package cross compiled
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- name: Get actual Go version
run: |
go version
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-cross-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-cross-${{ hashFiles('**/go.sum') }}
- name: Create packages - name: Create packages
run: | run: |
@@ -521,7 +465,7 @@ jobs:
goarch="${plat#*/}" goarch="${plat#*/}"
echo "::group ::$plat" echo "::group ::$plat"
for tgt in syncthing stdiscosrv strelaysrv ; do for tgt in syncthing stdiscosrv strelaysrv ; do
if ! go run build.go -goos "$goos" -goarch "$goarch" tar "$tgt" ; then if ! go run build.go -goos "$goos" -goarch "$goarch" tar "$tgt" 2>/dev/null; then
echo "::warning ::Failed to build $tgt for $plat" echo "::warning ::Failed to build $tgt for $plat"
fi fi
done done
@@ -543,33 +487,33 @@ jobs:
package-source: package-source:
name: Package source code name: Package source code
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- name: Package source - name: Package source
run: | run: |
echo "$VERSION" > RELEASE version=$(go run build.go version)
echo "$version" > RELEASE
go mod vendor go mod vendor
go run build.go assets go run build.go assets
cd .. cd ..
tar c -z -f "syncthing-source-$VERSION.tar.gz" \ tar c -z -f "syncthing-source-$version.tar.gz" \
--exclude .git \ --exclude .git \
syncthing syncthing
mv "syncthing-source-$VERSION.tar.gz" syncthing mv "syncthing-source-$version.tar.gz" syncthing
- name: Archive artifacts - name: Archive artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -583,7 +527,7 @@ jobs:
sign-for-upgrade: sign-for-upgrade:
name: Sign for upgrade name: Sign for upgrade
if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
environment: release environment: release
needs: needs:
- codesign-windows - codesign-windows
@@ -591,26 +535,27 @@ jobs:
- package-macos - package-macos
- package-cross - package-cross
- package-source - package-source
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
repository: syncthing/release-tools repository: syncthing/release-tools
path: tools path: tools
fetch-depth: 0
- name: Download artifacts - name: Download artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- name: Install signing tool - name: Install signing tool
run: | run: |
@@ -637,6 +582,9 @@ jobs:
sha256sum "${files[@]}" > sha256sum.txt sha256sum "${files[@]}" > sha256sum.txt
popd popd
version=$(go run build.go version)
echo "VERSION=$version" >> $GITHUB_ENV
- name: Sign shasum files - name: Sign shasum files
uses: docker://ghcr.io/kastelo/ezapt:latest uses: docker://ghcr.io/kastelo/ezapt:latest
with: with:
@@ -672,18 +620,22 @@ jobs:
package-debian: package-debian:
name: Package for Debian name: Package for Debian
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- name: Get actual Go version
run: |
go version
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
- uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@v1
with: with:
@@ -693,27 +645,22 @@ jobs:
run: | run: |
gem install fpm gem install fpm
- uses: mlugg/setup-zig@v2
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-debian-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-debian-${{ hashFiles('**/go.sum') }}
- name: Package for Debian (CGO) - name: Package for Debian
run: | run: |
for arch in amd64 i386 armhf armel arm64 ; do
for tgt in syncthing stdiscosrv strelaysrv ; do for tgt in syncthing stdiscosrv strelaysrv ; do
go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS_LINUX}}" -goos linux -goarch amd64 -cc "zig cc -target x86_64-linux-musl" deb "$tgt" go run build.go -no-upgrade -installsuffix=no-upgrade -goarch "$arch" deb "$tgt"
go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS_LINUX}}" -goos linux -goarch armel -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" deb "$tgt" done
go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS_LINUX}}" -goos linux -goarch armhf -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" deb "$tgt"
go run build.go -no-upgrade -installsuffix=no-upgrade -tags "${{env.TAGS_LINUX}}" -goos linux -goarch arm64 -cc "zig cc -target aarch64-linux-musl" deb "$tgt"
done done
env: env:
BUILD_USER: debian BUILD_USER: debian
CGO_ENABLED: "1"
EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
- name: Archive artifacts - name: Archive artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -727,17 +674,17 @@ jobs:
publish-nightly: publish-nightly:
name: Publish nightly build name: Publish nightly build
if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && startsWith(github.ref, 'refs/heads/release-nightly') if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && startsWith(github.ref, 'refs/heads/release-nightly')
environment: release environment: release
needs: needs:
- sign-for-upgrade - sign-for-upgrade
- facts
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
repository: syncthing/release-tools repository: syncthing/release-tools
path: tools path: tools
fetch-depth: 0
- name: Download artifacts - name: Download artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@@ -747,8 +694,9 @@ jobs:
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- name: Create release json - name: Create release json
run: | run: |
@@ -776,17 +724,13 @@ jobs:
publish-release-files: publish-release-files:
name: Publish release files name: Publish release files
if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/tags/v')) if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/tags/v'))
environment: release environment: release
permissions: permissions:
contents: write contents: write
needs: needs:
- sign-for-upgrade - sign-for-upgrade
- package-debian - package-debian
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -808,8 +752,14 @@ jobs:
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- name: Set version
run: |
version=$(go run build.go version)
echo "VERSION=$version" >> $GITHUB_ENV
- name: Push to object store (${{ env.VERSION }}) - name: Push to object store (${{ env.VERSION }})
uses: docker://docker.io/rclone/rclone:latest uses: docker://docker.io/rclone/rclone:latest
@@ -879,24 +829,42 @@ jobs:
publish-apt: publish-apt:
name: Publish APT name: Publish APT
if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v'))
environment: release environment: release
needs: needs:
- package-debian - package-debian
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
RELEASE_GENERATION: ${{ needs.facts.outputs.release-generation }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- name: Download packages - name: Download packages
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: debian-packages name: debian-packages
path: 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 # 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 - name: Pull archive
uses: docker://docker.io/rclone/rclone:latest uses: docker://docker.io/rclone/rclone:latest
env: env:
@@ -908,18 +876,15 @@ jobs:
RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }} RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
RCLONE_CONFIG_OBJSTORE_ACL: public-read RCLONE_CONFIG_OBJSTORE_ACL: public-read
with: with:
args: sync objstore:apt apt args: sync objstore:apt/dists dists
- name: Prepare packages
run: |
sudo chown -R $(id -u) apt/pool
mv packages/*.deb apt/pool
- name: Update archive - name: Update archive
uses: docker://ghcr.io/kastelo/ezapt:latest uses: docker://ghcr.io/kastelo/ezapt:latest
with: with:
args: args:
publish --root apt publish
--add packages
--dists dists
env: env:
EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }} EZAPT_KEYRING_BASE64: ${{ secrets.APT_GPG_KEYRING_BASE64 }}
@@ -934,23 +899,20 @@ jobs:
RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }} RCLONE_CONFIG_OBJSTORE_REGION: ${{ secrets.S3_REGION }}
RCLONE_CONFIG_OBJSTORE_ACL: public-read RCLONE_CONFIG_OBJSTORE_ACL: public-read
with: with:
args: sync -v --no-update-modtime apt objstore:apt args: sync -v --no-update-modtime dists objstore:apt/dists
# #
# Build and push (except for PRs) to GHCR. # Build and push to Docker Hub
# #
docker-ghcr: docker-syncthing:
name: Build and push Docker images (GHCR) name: Build and push Docker images
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release-nightly' || github.ref == 'refs/heads/infrastructure' || startsWith(github.ref, 'refs/tags/v'))
environment: docker
permissions: permissions:
contents: read contents: read
packages: write packages: write
needs:
- facts
env:
VERSION: ${{ needs.facts.outputs.version }}
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
strategy: strategy:
matrix: matrix:
pkg: pkg:
@@ -960,50 +922,64 @@ jobs:
include: include:
- pkg: syncthing - pkg: syncthing
dockerfile: Dockerfile dockerfile: Dockerfile
image: syncthing image: syncthing/syncthing
- pkg: strelaysrv - pkg: strelaysrv
dockerfile: Dockerfile.strelaysrv dockerfile: Dockerfile.strelaysrv
image: relaysrv image: syncthing/relaysrv
- pkg: stdiscosrv - pkg: stdiscosrv
dockerfile: Dockerfile.stdiscosrv dockerfile: Dockerfile.stdiscosrv
image: discosrv image: syncthing/discosrv
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- uses: mlugg/setup-zig@v2 - name: Get actual Go version
run: |
go version
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
path: | path: |
~/.cache/go-build ~/.cache/go-build
~/go/pkg/mod ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ needs.facts.outputs.go-version }}-docker-${{ matrix.pkg }}-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-docker-${{ matrix.pkg }}-${{ hashFiles('**/go.sum') }}
- name: Build binaries (CGO) - name: Build binaries
run: | run: |
# amd64 for arch in amd64 arm64 arm; do
go run build.go -goos linux -goarch amd64 -tags "${{env.TAGS_LINUX}}" -cc "zig cc -target x86_64-linux-musl" -no-upgrade build ${{ matrix.pkg }} go run build.go -goos linux -goarch "$arch" -no-upgrade build ${{ matrix.pkg }}
mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-amd64 mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-"$arch"
done
# arm64
go run build.go -goos linux -goarch arm64 -tags "${{env.TAGS_LINUX}}" -cc "zig cc -target aarch64-linux-musl" -no-upgrade build ${{ matrix.pkg }}
mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-arm64
# arm
go run build.go -goos linux -goarch arm -tags "${{env.TAGS_LINUX}}" -cc "zig cc -target arm-linux-musleabi -mcpu=arm1136j_s" -no-upgrade build ${{ matrix.pkg }}
mv ${{ matrix.pkg }} ${{ matrix.pkg }}-linux-arm
env: env:
CGO_ENABLED: "1" CGO_ENABLED: "0"
BUILD_USER: docker BUILD_USER: docker
EXTRA_LDFLAGS: "-linkmode=external -extldflags=-static"
- name: Check if we will be able to push images
run: |
if [[ "${{ secrets.DOCKERHUB_TOKEN }}" != "" ]]; then
echo "DOCKER_PUSH=true" >> $GITHUB_ENV;
fi
- name: Login to Docker Hub
uses: docker/login-action@v3
if: env.DOCKER_PUSH == 'true'
with:
registry: docker.io
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR - name: Login to GHCR
uses: docker/login-action@v3 uses: docker/login-action@v3
if: env.DOCKER_PUSH == 'true'
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -1014,26 +990,22 @@ jobs:
- name: Set version tags - name: Set version tags
run: | run: |
version=${VERSION#v} version=$(go run build.go version)
repo=ghcr.io/${{ github.repository_owner }}/${{ matrix.image }} version=${version#v}
ref="${{github.ref_name}}"
ref=${ref//\//-} # slashes to dashes
# List of tags for ghcr.io
if [[ $version == @([0-9]|[0-9][0-9]).@([0-9]|[0-9][0-9]).@([0-9]|[0-9][0-9]) ]] ; then if [[ $version == @([0-9]|[0-9][0-9]).@([0-9]|[0-9][0-9]).@([0-9]|[0-9][0-9]) ]] ; then
echo Release version, pushing to :latest and version tags
major=${version%.*.*} major=${version%.*.*}
minor=${version%.*} minor=${version%.*}
tags=$repo:$version,$repo:$major,$repo:$minor,$repo:latest tags=docker.io/${{ matrix.image }}:$version,ghcr.io/${{ matrix.image }}:$version,docker.io/${{ matrix.image }}:$major,ghcr.io/${{ matrix.image }}:$major,docker.io/${{ matrix.image }}:$minor,ghcr.io/${{ matrix.image }}:$minor,docker.io/${{ matrix.image }}:latest,ghcr.io/${{ matrix.image }}:latest
elif [[ $version == *-rc.@([0-9]|[0-9][0-9]) ]] ; then elif [[ $version == *-rc.@([0-9]|[0-9][0-9]) ]] ; then
tags=$repo:$version,$repo:rc echo Release candidate, pushing to :rc and version tags
elif [[ $ref == "main" ]] ; then tags=docker.io/${{ matrix.image }}:$version,ghcr.io/${{ matrix.image }}:$version,docker.io/${{ matrix.image }}:rc,ghcr.io/${{ matrix.image }}:rc
tags=$repo:edge
else else
tags=$repo:$ref echo Development version, pushing to :edge
tags=docker.io/${{ matrix.image }}:edge,ghcr.io/${{ matrix.image }}:edge
fi fi
echo Pushing to $tags
echo "DOCKER_TAGS=$tags" >> $GITHUB_ENV echo "DOCKER_TAGS=$tags" >> $GITHUB_ENV
echo "VERSION=$version" >> $GITHUB_ENV
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
@@ -1041,36 +1013,12 @@ jobs:
context: . context: .
file: ${{ matrix.dockerfile }} file: ${{ matrix.dockerfile }}
platforms: linux/amd64,linux/arm64,linux/arm/7 platforms: linux/amd64,linux/arm64,linux/arm/7
push: ${{ env.DOCKER_PUSH == 'true' }}
tags: ${{ env.DOCKER_TAGS }} tags: ${{ env.DOCKER_TAGS }}
push: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
labels: | labels: |
org.opencontainers.image.version=${{ env.VERSION }} org.opencontainers.image.version=${{ env.VERSION }}
org.opencontainers.image.revision=${{ github.sha }} org.opencontainers.image.revision=${{ github.sha }}
#
# Sync images to Docker hub. This takes the images already pushed to GHCR
# and copies them to Docker hub. Runs for releases only.
#
docker-hub:
name: Sync images to Docker hub
if: github.repository_owner == 'syncthing' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release-nightly' || github.ref == 'refs/heads/infrastructure' || startsWith(github.ref, 'refs/tags/v'))
runs-on: ubuntu-latest
needs:
- docker-ghcr
environment: docker
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Sync images
uses: docker://docker.io/regclient/regsync:latest
with:
args:
-c ./.github/regsync.yml
once
# #
# Check for known vulnerabilities in Go dependencies # Check for known vulnerabilities in Go dependencies
# #
@@ -1078,57 +1026,17 @@ jobs:
govulncheck: govulncheck:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Run govulncheck name: Run govulncheck
needs:
- facts
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: ${{ needs.facts.outputs.go-version }} go-version: ${{ env.GO_VERSION }}
cache: false cache: false
check-latest: true
- name: run govulncheck - name: run govulncheck
run: | run: |
go run build.go assets go run build.go assets
go install golang.org/x/vuln/cmd/govulncheck@latest go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./... govulncheck ./...
#
# golangci-lint runs a suite of static analysis checks on the code
#
golangci:
runs-on: ubuntu-latest
name: Run golangci-lint
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- name: ensure asset generation
run: go run build.go assets
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
with:
only-new-issues: true
#
# Meta checks for formatting, copyright, etc
#
meta:
name: Run meta checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- run: |
go run build.go assets
go test -v ./meta
-18
View File
@@ -1,18 +0,0 @@
name: Mirrors
on: [push, delete]
jobs:
codeberg:
name: Mirror to Codeberg
if: github.repository_owner == 'syncthing'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: ssh://git@codeberg.org/${{ github.repository }}.git
GIT_SSH_PRIVATE_KEY: ${{ secrets.CODEBERG_PUSH_KEY }}
GIT_SSH_NO_VERIFY_HOST: "true"
+49
View File
@@ -0,0 +1,49 @@
name: Run PR linters
on:
pull_request:
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
#
# golangci-lint runs a suite of static analysis checks on the code
#
golangci:
runs-on: ubuntu-latest
name: Golangci-lint
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- name: ensure asset generation
run: go run build.go assets
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
with:
only-new-issues: true
#
# Meta checks for formatting, copyright, etc
#
meta:
name: Meta checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- run: |
go run build.go assets
go test -v ./meta
+1
View File
@@ -17,4 +17,5 @@ deb
*.bz2 *.bz2
/repos /repos
/proto/scripts/protoc-gen-gosyncthing /proto/scripts/protoc-gen-gosyncthing
/gui/next-gen-gui
/compat.json /compat.json
-23
View File
@@ -4,18 +4,15 @@ linters:
disable: disable:
- cyclop - cyclop
- depguard - depguard
- err113
- exhaustive - exhaustive
- exhaustruct - exhaustruct
- forbidigo - forbidigo
- funcorder
- funlen - funlen
- gochecknoglobals - gochecknoglobals
- gochecknoinits - gochecknoinits
- gocognit - gocognit
- goconst - goconst
- gocyclo - gocyclo
- godot
- godox - godox
- gomoddirectives - gomoddirectives
- inamedparam - inamedparam
@@ -27,7 +24,6 @@ linters:
- musttag - musttag
- nestif - nestif
- nlreturn - nlreturn
- noinlineerr
- nonamedreturns - nonamedreturns
- paralleltest - paralleltest
- prealloc - prealloc
@@ -43,7 +39,6 @@ linters:
- whitespace - whitespace
- wrapcheck - wrapcheck
- wsl - wsl
- wsl_v5
exclusions: exclusions:
generated: lax generated: lax
presets: presets:
@@ -53,29 +48,11 @@ linters:
- std-error-handling - std-error-handling
paths: paths:
- internal/gen - internal/gen
- internal/db/olddb
- cmd/dev - cmd/dev
- repos - repos
- third_party$ - third_party$
- builtin$ - builtin$
- examples$ - examples$
- _test\.go$
rules:
# relax the slog rules for debug lines, for now
- linters: [sloglint]
source: Debug
# contexts are irrelevant for SQLite
- linters: [noctx]
text: database/sql
# Rollback errors can be ignored
- linters: [errcheck]
source: Rollback
settings:
sloglint:
context: "scope"
static-msg: true
msg-style: capitalized
key-naming-case: camel
formatters: formatters:
enable: enable:
- gofumpt - gofumpt
+78 -28
View File
@@ -13,100 +13,104 @@
# contents of this file. # contents of this file.
# #
Jakob Borg (calmh) <jakob@nym.se> <jakob@kastelo.net> <jborg@coreweave.com> Aaron Bieber (qbit) <qbit@deftly.net>
Audrius Butkevicius (AudriusButkevicius) <audrius.butkevicius@gmail.com> <github@audrius.rocks>
Simon Frei (imsodin) <freisim93@gmail.com>
Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com> <twilczynski@naver.com>
Alexander Graf (alex2108) <register-github@alex-graf.de>
Alexandre Viau (aviau) <alexandre@alexandreviau.net> <aviau@debian.org>
Anderson Mesquita (andersonvom) <andersonvom@gmail.com>
André Colomb (acolomb) <src@andre.colomb.de> <github.com@andre.colomb.de>
Antony Male (canton7) <antony.male@gmail.com>
Ben Schulz (uok) <ueomkail@gmail.com> <uok@users.noreply.github.com>
bt90 <btom1990@googlemail.com>
Caleb Callaway (cqcallaw) <enlightened.despot@gmail.com>
Daniel Harte (norgeous) <daniel@harte.me> <daniel@danielharte.co.uk> <norgeous@users.noreply.github.com>
Emil Lundberg <emil@emlun.se>
Eric P <eric@kastelo.net>
Evgeny Kuznetsov <evgeny@kuznetsov.md>
greatroar <61184462+greatroar@users.noreply.github.com>
Lars K.W. Gohlke (lkwg82) <lkwg82@gmx.de>
Lode Hoste (Zillode) <zillode@zillode.be>
Michael Ploujnikov (plouj) <ploujj@gmail.com>
Ross Smith II (rasa) <ross@smithii.com>
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org> <stefan@rumpelsepp.org>
Tommy van der Vorst <tommy-github@pixelspark.nl> <tommy@pixelspark.nl>
Wulf Weich (wweich) <wweich@users.noreply.github.com> <wweich@gmx.de> <wulf@weich-kr.de>
Adam Piggott (ProactiveServices) <aD@simplypeachy.co.uk> <simplypeachy@users.noreply.github.com> <ProactiveServices@users.noreply.github.com> <adam@proactiveservices.co.uk> Adam Piggott (ProactiveServices) <aD@simplypeachy.co.uk> <simplypeachy@users.noreply.github.com> <ProactiveServices@users.noreply.github.com> <adam@proactiveservices.co.uk>
Adel Qalieh (adelq) <aqalieh95@gmail.com> <adelq@users.noreply.github.com> Adel Qalieh (adelq) <aqalieh95@gmail.com> <adelq@users.noreply.github.com>
Alan Pope <alan@popey.com>
Alberto Donato <albertodonato@users.noreply.github.com>
Aleksey Vasenev <margtu-fivt@ya.ru> Aleksey Vasenev <margtu-fivt@ya.ru>
Alessandro G. (alessandro.g89) <alessandro.g89@gmail.com> Alessandro G. (alessandro.g89) <alessandro.g89@gmail.com>
Alex Ionescu <github@ionescu.sh> Alex Ionescu <github@ionescu.sh>
Alex Lindeman <139387+aelindeman@users.noreply.github.com> Alex Lindeman <139387+aelindeman@users.noreply.github.com>
Alex Xu <alex.hello71@gmail.com> Alex Xu <alex.hello71@gmail.com>
Alexander Graf (alex2108) <register-github@alex-graf.de>
Alexander Seiler <seileralex@gmail.com> Alexander Seiler <seileralex@gmail.com>
Alexandre Alves <alexandrealvesdb.contact@gmail.com> Alexandre Alves <alexandrealvesdb.contact@gmail.com>
Alexandre Viau (aviau) <alexandre@alexandreviau.net> <aviau@debian.org>
Aman Gupta <aman@tmm1.net> Aman Gupta <aman@tmm1.net>
Anatoli Babenia <anatoli@rainforce.org>
Anderson Mesquita (andersonvom) <andersonvom@gmail.com>
Andreas Sommer <andreas.sommer87@googlemail.com> Andreas Sommer <andreas.sommer87@googlemail.com>
andresvia <andres.via@gmail.com> andresvia <andres.via@gmail.com>
Andrew Dunham (andrew-d) <andrew@du.nham.ca>
Andrew Meyer <andrewm.bpi@gmail.com>
Andrew Rabert (nvllsvm) <ar@nullsum.net> <6550543+nvllsvm@users.noreply.github.com> Andrew Rabert (nvllsvm) <ar@nullsum.net> <6550543+nvllsvm@users.noreply.github.com>
Andrey D (scienmind) <scintertech@cryptolab.net> <scienmind@users.noreply.github.com> Andrey D (scienmind) <scintertech@cryptolab.net> <scienmind@users.noreply.github.com>
André Colomb (acolomb) <src@andre.colomb.de> <github.com@andre.colomb.de>
andyleap <andyleap@gmail.com> andyleap <andyleap@gmail.com>
Anjan Momi <anjan@momi.ca> Anjan Momi <anjan@momi.ca>
Anthony Goeckner <agoeckner@users.noreply.github.com> Anthony Goeckner <agoeckner@users.noreply.github.com>
Antoine Lamielle (0x010C) <antoine.lamielle@0x010c.fr> <gh@0x010c.fr> Antoine Lamielle (0x010C) <antoine.lamielle@0x010c.fr> <gh@0x010c.fr>
Antony Male (canton7) <antony.male@gmail.com>
Anur <anurnomeru@163.com> Anur <anurnomeru@163.com>
Aranjedeath <Aranjedeath@users.noreply.github.com> Aranjedeath <Aranjedeath@users.noreply.github.com>
ardevd <ardevd@users.noreply.github.com>
Arkadiusz Tymiński <gevleeog@gmail.com> Arkadiusz Tymiński <gevleeog@gmail.com>
Aroun <login@b-vo.fr> Aroun <login@b-vo.fr>
Arthur Axel fREW Schmidt (frioux) <frew@afoolishmanifesto.com> <frioux@gmail.com> Arthur Axel fREW Schmidt (frioux) <frew@afoolishmanifesto.com> <frioux@gmail.com>
Artur Zubilewicz <AkaZecik@users.noreply.github.com> Artur Zubilewicz <AkaZecik@users.noreply.github.com>
Ashish Bhate <bhate.ashish@gmail.com> Ashish Bhate <bhate.ashish@gmail.com>
Audrius Butkevicius (AudriusButkevicius) <audrius.butkevicius@gmail.com> <github@audrius.rocks>
Aurélien Rainone <476650+arl@users.noreply.github.com> Aurélien Rainone <476650+arl@users.noreply.github.com>
BAHADIR YILMAZ <bahadiryilmaz32@gmail.com> BAHADIR YILMAZ <bahadiryilmaz32@gmail.com>
Bart De Vries (mogwa1) <devriesb@gmail.com> Bart De Vries (mogwa1) <devriesb@gmail.com>
Beat Reichenbach <44111292+beatreichenbach@users.noreply.github.com> Beat Reichenbach <44111292+beatreichenbach@users.noreply.github.com>
Ben Curthoys (bencurthoys) <ben@bencurthoys.com>
Ben Schulz (uok) <ueomkail@gmail.com> <uok@users.noreply.github.com>
Ben Shepherd (benshep) <bjashepherd@gmail.com> Ben Shepherd (benshep) <bjashepherd@gmail.com>
Ben Sidhom (bsidhom) <bsidhom@gmail.com> Ben Sidhom (bsidhom) <bsidhom@gmail.com>
Benedikt Heine (bebehei) <bebe@bebehei.de> Benedikt Heine (bebehei) <bebe@bebehei.de>
Benedikt Morbach <benedikt.morbach@googlemail.com>
Benjamin Nater <17193640+bn4t@users.noreply.github.com>
Benno Fünfstück <benno.fuenfstueck@gmail.com> Benno Fünfstück <benno.fuenfstueck@gmail.com>
Benny Ng (tpng) <benny.tpng@gmail.com> Benny Ng (tpng) <benny.tpng@gmail.com>
boomsquared <54829195+boomsquared@users.noreply.github.com> boomsquared <54829195+boomsquared@users.noreply.github.com>
Boqin Qin <bobbqqin@bupt.edu.cn> Boqin Qin <bobbqqin@bupt.edu.cn>
Boris Rybalkin <ribalkin@gmail.com> Boris Rybalkin <ribalkin@gmail.com>
Brandon Philips (philips) <brandon@ifup.org>
Brendan Long (brendanlong) <self@brendanlong.com> Brendan Long (brendanlong) <self@brendanlong.com>
Brian R. Becker (brbecker) <brbecker@gmail.com>
bt90 <btom1990@googlemail.com>
Caleb Callaway (cqcallaw) <enlightened.despot@gmail.com>
Carsten Hagemann (carstenhag) <moter8@gmail.com> <carsten@chagemann.de>
Catfriend1 <16361913+Catfriend1@users.noreply.github.com> Catfriend1 <16361913+Catfriend1@users.noreply.github.com>
Cathryne Linenweaver (Cathryne) <cathryne.linenweaver@gmail.com> <Cathryne@users.noreply.github.com> <katrinleinweber@MAC.local> Cathryne Linenweaver (Cathryne) <cathryne.linenweaver@gmail.com> <Cathryne@users.noreply.github.com> <katrinleinweber@MAC.local>
Cedric Staniewski (xduugu) <cedric@gmx.ca> Cedric Staniewski (xduugu) <cedric@gmx.ca>
chenrui <rui@meetup.com>
Chih-Hsuan Yen <yan12125@gmail.com> <1937689+yan12125@users.noreply.github.com> Chih-Hsuan Yen <yan12125@gmail.com> <1937689+yan12125@users.noreply.github.com>
Choongkyu <choongkyu.kim+gh@gmail.com> <vapidlyrapid+gh@gmail.com> Choongkyu <choongkyu.kim+gh@gmail.com> <vapidlyrapid+gh@gmail.com>
Chris Howie (cdhowie) <me@chrishowie.com> Chris Howie (cdhowie) <me@chrishowie.com>
Chris Joel (cdata) <chris@scriptolo.gy> Chris Joel (cdata) <chris@scriptolo.gy>
Chris Tonkinson <chris@masterbran.ch>
Christian Kujau <ckujau@users.noreply.github.com> Christian Kujau <ckujau@users.noreply.github.com>
Christian Prescott <me@christianprescott.com> Christian Prescott <me@christianprescott.com>
chucic <chucic@seznam.cz> chucic <chucic@seznam.cz>
cjc7373 <niuchangcun@gmail.com> cjc7373 <niuchangcun@gmail.com>
Colin Kennedy (moshen) <moshen.colin@gmail.com> Colin Kennedy (moshen) <moshen.colin@gmail.com>
Cromefire_ <tim.l@nghorst.net> <26320625+cromefire@users.noreply.github.com> Cromefire_ <tim.l@nghorst.net> <26320625+cromefire@users.noreply.github.com>
cui fliter <imcusg@gmail.com>
Cyprien Devillez <cypx@users.noreply.github.com> Cyprien Devillez <cypx@users.noreply.github.com>
d-volution <49024624+d-volution@users.noreply.github.com> d-volution <49024624+d-volution@users.noreply.github.com>
Dale Visser <dale.visser@live.com>
Dan <benda.daniel@gmail.com> Dan <benda.daniel@gmail.com>
Daniel Barczyk <46358936+DanielBarczyk@users.noreply.github.com> Daniel Barczyk <46358936+DanielBarczyk@users.noreply.github.com>
Daniel Bergmann (brgmnn) <dan.arne.bergmann@gmail.com> <brgmnn@users.noreply.github.com> Daniel Bergmann (brgmnn) <dan.arne.bergmann@gmail.com> <brgmnn@users.noreply.github.com>
Daniel Harte (norgeous) <daniel@harte.me> <daniel@danielharte.co.uk> <norgeous@users.noreply.github.com>
Daniel Martí (mvdan) <mvdan@mvdan.cc> Daniel Martí (mvdan) <mvdan@mvdan.cc>
Daniel Padrta <64928366+danpadcz@users.noreply.github.com> Daniel Padrta <64928366+danpadcz@users.noreply.github.com>
Daniil Gentili <daniil@daniil.it>
Darshil Chanpura (dtchanpura) <dtchanpura@gmail.com> <dcprime314@gmail.com> Darshil Chanpura (dtchanpura) <dtchanpura@gmail.com> <dcprime314@gmail.com>
dashangcun <907225865@qq.com> dashangcun <907225865@qq.com>
David Rimmer (dinosore) <dinosore@dbrsoftware.co.uk> David Rimmer (dinosore) <dinosore@dbrsoftware.co.uk>
deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com>
DeflateAwning <11021263+DeflateAwning@users.noreply.github.com> DeflateAwning <11021263+DeflateAwning@users.noreply.github.com>
Denis A. (dva) <denisva@gmail.com> Denis A. (dva) <denisva@gmail.com>
Dennis Wilson (snnd) <dw@risu.io> Dennis Wilson (snnd) <dw@risu.io>
dependabot-preview[bot] <dependabot-preview[bot]@users.noreply.github.com> <27856297+dependabot-preview[bot]@users.noreply.github.com>
dependabot[bot] <dependabot[bot]@users.noreply.github.com> <49699333+dependabot[bot]@users.noreply.github.com>
derekriemer <derek.riemer@colorado.edu> derekriemer <derek.riemer@colorado.edu>
DerRockWolf <50499906+DerRockWolf@users.noreply.github.com> DerRockWolf <50499906+DerRockWolf@users.noreply.github.com>
desbma <desbma@users.noreply.github.com> desbma <desbma@users.noreply.github.com>
Devon G. Redekopp <devon@redekopp.com> Devon G. Redekopp <devon@redekopp.com>
diemade <spamkill@posteo.ch>
digital <didev@dinid.net> digital <didev@dinid.net>
Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com> Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com>
Dmitry Saveliev (dsaveliev) <d.e.saveliev@gmail.com> Dmitry Saveliev (dsaveliev) <d.e.saveliev@gmail.com>
@@ -116,11 +120,14 @@ Dominik Heidler (asdil12) <dominik@heidler.eu>
Elias Jarlebring (jarlebring) <jarlebring@gmail.com> Elias Jarlebring (jarlebring) <jarlebring@gmail.com>
Elliot Huffman <thelich2@gmail.com> Elliot Huffman <thelich2@gmail.com>
Emil Hessman (ceh) <emil@hessman.se> Emil Hessman (ceh) <emil@hessman.se>
Emil Lundberg <emil@emlun.se>
Eng Zer Jun <engzerjun@gmail.com> Eng Zer Jun <engzerjun@gmail.com>
entity0xfe <109791748+entity0xfe@users.noreply.github.com> <entity0xfe@my.domain> entity0xfe <109791748+entity0xfe@users.noreply.github.com> <entity0xfe@my.domain>
Eric Lesiuta <elesiuta@gmail.com> Eric Lesiuta <elesiuta@gmail.com>
Eric P <eric@kastelo.net>
Erik Meitner (WSGCSysadmin) <e.meitner@willystreet.coop> Erik Meitner (WSGCSysadmin) <e.meitner@willystreet.coop>
Evan Spensley <94762716+0evan@users.noreply.github.com> Evan Spensley <94762716+0evan@users.noreply.github.com>
Evgeny Kuznetsov <evgeny@kuznetsov.md>
Federico Castagnini (facastagnini) <federico.castagnini@gmail.com> Federico Castagnini (facastagnini) <federico.castagnini@gmail.com>
Felix <53702818+f-eliks@users.noreply.github.com> Felix <53702818+f-eliks@users.noreply.github.com>
Felix Ableitner (Nutomic) <me@nutomic.com> Felix Ableitner (Nutomic) <me@nutomic.com>
@@ -134,6 +141,7 @@ ghjklw <malo@jaffre.info>
Gilli Sigurdsson (gillisig) <gilli@vx.is> Gilli Sigurdsson (gillisig) <gilli@vx.is>
Gleb Sinyavskiy <zhulik.gleb@gmail.com> Gleb Sinyavskiy <zhulik.gleb@gmail.com>
Graham Miln (grahammiln) <graham.miln@dssw.co.uk> <graham.miln@miln.eu> Graham Miln (grahammiln) <graham.miln@dssw.co.uk> <graham.miln@miln.eu>
greatroar <61184462+greatroar@users.noreply.github.com>
Greg <gco@jazzhaiku.com> Greg <gco@jazzhaiku.com>
guangwu <guoguangwu@magic-shield.com> guangwu <guoguangwu@magic-shield.com>
gudvinr <gudvinr@gmail.com> gudvinr <gudvinr@gmail.com>
@@ -148,35 +156,50 @@ Hugo Locurcio <hugo.locurcio@hugo.pro>
Iain Barnett <iainspeed@gmail.com> Iain Barnett <iainspeed@gmail.com>
Ian Johnson (anonymouse64) <ian.johnson@canonical.com> <person.uwsome@gmail.com> Ian Johnson (anonymouse64) <ian.johnson@canonical.com> <person.uwsome@gmail.com>
ignacy123 <ignacy.buczek@onet.pl> ignacy123 <ignacy.buczek@onet.pl>
Ikko Ashimine <eltociear@gmail.com>
Ilya Brin <464157+ilyabrin@users.noreply.github.com>
Iskander Sharipov (Alex) <quasilyte@gmail.com> Iskander Sharipov (Alex) <quasilyte@gmail.com>
Jaakko Hannikainen (jgke) <jgke@jgke.fi> Jaakko Hannikainen (jgke) <jgke@jgke.fi>
Jacek Szafarkiewicz (hadogenes) <szafar@linux.pl>
Jack Croft <jccroft1@users.noreply.github.com> Jack Croft <jccroft1@users.noreply.github.com>
Jacob <jyundt@gmail.com> Jacob <jyundt@gmail.com>
Jake Peterson (acogdev) <jake@acogdev.com> Jake Peterson (acogdev) <jake@acogdev.com>
Jakob Borg (calmh) <jakob@nym.se> <jakob@kastelo.net> <jborg@coreweave.com>
James O'Beirne <wild-github@au92.org> James O'Beirne <wild-github@au92.org>
James Patterson (jpjp) <jamespatterson@operamail.com> <jpjp@users.noreply.github.com> James Patterson (jpjp) <jamespatterson@operamail.com> <jpjp@users.noreply.github.com>
janost <janost@tuta.io>
Jaroslav Lichtblau <svetlemodry@users.noreply.github.com> Jaroslav Lichtblau <svetlemodry@users.noreply.github.com>
Jaroslav Malec (dzarda) <dzardacz@gmail.com> Jaroslav Malec (dzarda) <dzardacz@gmail.com>
jaseg <githubaccount@jaseg.net>
Jaspitta <ste.scarpitta@gmail.com> Jaspitta <ste.scarpitta@gmail.com>
Jauder Ho <jauderho@users.noreply.github.com>
Jaya Chithra (jayachithra) <s.k.jayachithra@gmail.com> Jaya Chithra (jayachithra) <s.k.jayachithra@gmail.com>
Jaya Kumar <jaya.kumar@ict.nl> Jaya Kumar <jaya.kumar@ict.nl>
Jeffery To <jeffery.to@gmail.com> Jeffery To <jeffery.to@gmail.com>
jelle van der Waa <jelle@vdwaa.nl> jelle van der Waa <jelle@vdwaa.nl>
Jens Diemer (jedie) <github.com@jensdiemer.de> <git@jensdiemer.de> Jens Diemer (jedie) <github.com@jensdiemer.de> <git@jensdiemer.de>
Jerry Jacobs (xor-gate) <jerry.jacobs@xor-gate.org> <xor-gate@users.noreply.github.com>
Jesse Lucas <jesse@jesselucas.com>
Jochen Voss (seehuhn) <voss@seehuhn.de> Jochen Voss (seehuhn) <voss@seehuhn.de>
Johan Andersson <j@i19.se>
Johan Vromans (sciurius) <jvromans@squirrel.nl> Johan Vromans (sciurius) <jvromans@squirrel.nl>
John Rinehart (fuzzybear3965) <johnrichardrinehart@gmail.com> John Rinehart (fuzzybear3965) <johnrichardrinehart@gmail.com>
Jonas Thelemann <e-mail@jonas-thelemann.de> Jonas Thelemann <e-mail@jonas-thelemann.de>
Jonathan <artback@protonmail.com> <jonagn@gmail.com> Jonathan <artback@protonmail.com> <jonagn@gmail.com>
Jonathan Cross <jcross@gmail.com>
Jonta <359397+Jonta@users.noreply.github.com>
Jose Manuel Delicado (jmdaweb) <jmdaweb@hotmail.com> <jmdaweb@users.noreply.github.com> Jose Manuel Delicado (jmdaweb) <jmdaweb@hotmail.com> <jmdaweb@users.noreply.github.com>
jtagcat <git-514635f7@jtag.cat> <git-12dbd862@jtag.cat> jtagcat <git-514635f7@jtag.cat> <git-12dbd862@jtag.cat>
Julian Lehrhuber <jul13579@users.noreply.github.com> Julian Lehrhuber <jul13579@users.noreply.github.com>
Jörg Thalheim <Mic92@users.noreply.github.com> Jörg Thalheim <Mic92@users.noreply.github.com>
Jędrzej Kula <kula.jedrek@gmail.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> Kapil Sareen <kapilsareen584@gmail.com>
Karol Różycki (krozycki) <rozycki.karol@gmail.com> Karol Różycki (krozycki) <rozycki.karol@gmail.com>
Kebin Liu <lkebin@gmail.com> Kebin Liu <lkebin@gmail.com>
Keith Harrison <keithh@protonmail.com> Keith Harrison <keithh@protonmail.com>
Keith Turner <kturner@apache.org>
Kelong Cong (kc1212) <kc04bc@gmx.com> <kc1212@users.noreply.github.com> Kelong Cong (kc1212) <kc04bc@gmx.com> <kc1212@users.noreply.github.com>
Ken'ichi Kamada (kamadak) <kamada@nanohz.org> Ken'ichi Kamada (kamadak) <kamada@nanohz.org>
Kevin Allen (ironmig) <kma1660@gmail.com> Kevin Allen (ironmig) <kma1660@gmail.com>
@@ -185,24 +208,31 @@ Kevin White, Jr. (kwhite17) <kevinwhite1710@gmail.com>
klemens <ka7@github.com> klemens <ka7@github.com>
Kurt Fitzner (Kudalufi) <kurt@va1der.ca> <kurt.fitzner@gmail.com> Kurt Fitzner (Kudalufi) <kurt@va1der.ca> <kurt.fitzner@gmail.com>
kylosus <33132401+kylosus@users.noreply.github.com> kylosus <33132401+kylosus@users.noreply.github.com>
Lars K.W. Gohlke (lkwg82) <lkwg82@gmx.de>
Lars Lehtonen <lars.lehtonen@gmail.com> Lars Lehtonen <lars.lehtonen@gmail.com>
Laurent Arnoud <laurent@spkdev.net>
Laurent Etiemble (letiemble) <laurent.etiemble@gmail.com> <laurent.etiemble@monobjc.net> Laurent Etiemble (letiemble) <laurent.etiemble@gmail.com> <laurent.etiemble@monobjc.net>
Leo Arias (elopio) <yo@elopio.net> Leo Arias (elopio) <yo@elopio.net>
Liu Siyuan (liusy182) <liusy182@gmail.com> <liusy182@hotmail.com> Liu Siyuan (liusy182) <liusy182@gmail.com> <liusy182@hotmail.com>
Lode Hoste (Zillode) <zillode@zillode.be>
Lord Landon Agahnim (LordLandon) <lordlandon@gmail.com> Lord Landon Agahnim (LordLandon) <lordlandon@gmail.com>
LSmithx2 <42276854+lsmithx2@users.noreply.github.com> LSmithx2 <42276854+lsmithx2@users.noreply.github.com>
luchenhan <168071714+luchenhan@users.noreply.github.com>
Lukas Lihotzki <lukas@lihotzki.de> Lukas Lihotzki <lukas@lihotzki.de>
Luke Hamburg <1992842+luckman212@users.noreply.github.com> Luke Hamburg <1992842+luckman212@users.noreply.github.com>
luzpaz <luzpaz@users.noreply.github.com> luzpaz <luzpaz@users.noreply.github.com>
Majed Abdulaziz (majedev) <majed.alhajry@gmail.com> Majed Abdulaziz (majedev) <majed.alhajry@gmail.com>
Marc Laporte (marclaporte) <marc@marclaporte.com> <marc@laporte.name> Marc Laporte (marclaporte) <marc@marclaporte.com> <marc@laporte.name>
Marc Pujol (kilburn) <kilburn@la3.org>
Marcel Meyer <mm.marcelmeyer@gmail.com> Marcel Meyer <mm.marcelmeyer@gmail.com>
Marcin Dziadus (marcindziadus) <dziadus.marcin@gmail.com> Marcin Dziadus (marcindziadus) <dziadus.marcin@gmail.com>
marco-m <marco.molteni@laposte.net>
Marcus B Spencer <marcus@marcusspencer.xyz> <marcus@marcusspencer.us> Marcus B Spencer <marcus@marcusspencer.xyz> <marcus@marcusspencer.us>
Marcus Legendre <marcus.legendre@gmail.com> Marcus Legendre <marcus.legendre@gmail.com>
Mario Majila <mariustshipichik@gmail.com> Mario Majila <mariustshipichik@gmail.com>
Mark Pulford (mpx) <mark@kyne.com.au> Mark Pulford (mpx) <mark@kyne.com.au>
Martchus <martchus@gmx.net> Martchus <martchus@gmx.net>
Martin Polehla <p0l0us@users.noreply.github.com>
Mateusz Naściszewski (mateon1) <matin1111@wp.pl> Mateusz Naściszewski (mateon1) <matin1111@wp.pl>
Mateusz Ż <thedead4fun@live.com> Mateusz Ż <thedead4fun@live.com>
mathias4833 <67101597+mathias4833@users.noreply.github.com> mathias4833 <67101597+mathias4833@users.noreply.github.com>
@@ -213,10 +243,15 @@ Matteo Ruina <matteo.ruina@gmail.com>
Maurizio Tomasi <ziotom78@gmail.com> Maurizio Tomasi <ziotom78@gmail.com>
Max <github@germancoding.com> Max <github@germancoding.com>
Max Schulze (kralo) <max.schulze@online.de> <kralo@users.noreply.github.com> Max Schulze (kralo) <max.schulze@online.de> <kralo@users.noreply.github.com>
maxice8 <30738253+maxice8@users.noreply.github.com>
MaximAL <almaximal@ya.ru> MaximAL <almaximal@ya.ru>
Maxime Thirouin <m@moox.io>
Maximilian <maxi.rostock@outlook.de> <public@complexvector.space> Maximilian <maxi.rostock@outlook.de> <public@complexvector.space>
mclang <1721600+mclang@users.noreply.github.com>
Michael Jephcote (Rewt0r) <rewt0r@gmx.com> <Rewt0r@users.noreply.github.com> Michael Jephcote (Rewt0r) <rewt0r@gmx.com> <Rewt0r@users.noreply.github.com>
Michael Ploujnikov (plouj) <ploujj@gmail.com>
Michael Rienstra <mrienstra@gmail.com> Michael Rienstra <mrienstra@gmail.com>
Michael Tilli (pyfisch) <pyfisch@gmail.com>
MichaIng <micha@dietpi.com> MichaIng <micha@dietpi.com>
Migelo <miha@filetki.si> Migelo <miha@filetki.si>
Mike Boone <mike@boonedocks.net> Mike Boone <mike@boonedocks.net>
@@ -225,6 +260,7 @@ MikolajTwarog <43782609+MikolajTwarog@users.noreply.github.com>
Mingxuan Lin <gdlmx@users.noreply.github.com> Mingxuan Lin <gdlmx@users.noreply.github.com>
mv1005 <49659413+mv1005@users.noreply.github.com> mv1005 <49659413+mv1005@users.noreply.github.com>
Nate Morrison (nrm21) <natemorrison@gmail.com> Nate Morrison (nrm21) <natemorrison@gmail.com>
Naveen <172697+naveensrinivasan@users.noreply.github.com>
nf <nf@wh3rd.net> nf <nf@wh3rd.net>
Nicholas Rishel (PrototypeNM1) <rishel.nick@gmail.com> <PrototypeNM1@users.noreply.github.com> Nicholas Rishel (PrototypeNM1) <rishel.nick@gmail.com> <PrototypeNM1@users.noreply.github.com>
Nick Busey <NickBusey@users.noreply.github.com> Nick Busey <NickBusey@users.noreply.github.com>
@@ -239,6 +275,7 @@ NoLooseEnds <jon.koslung@gmail.com>
Oliver Freyermuth <o.freyermuth@googlemail.com> Oliver Freyermuth <o.freyermuth@googlemail.com>
orangekame3 <miya.org.0309@gmail.com> orangekame3 <miya.org.0309@gmail.com>
otbutz <tbutz@optitool.de> otbutz <tbutz@optitool.de>
Otiel <Otiel@users.noreply.github.com>
overkill <22098433+0verk1ll@users.noreply.github.com> overkill <22098433+0verk1ll@users.noreply.github.com>
Oyebanji Jacob Mayowa <oyebanji05@gmail.com> Oyebanji Jacob Mayowa <oyebanji05@gmail.com>
Pablo <pbaeyens31+github@gmail.com> Pablo <pbaeyens31+github@gmail.com>
@@ -246,6 +283,7 @@ Pascal Jungblut (pascalj) <github@pascalj.com> <mail@pascal-jungblut.com>
Paul Brit <paulbrit44@gmail.com> Paul Brit <paulbrit44@gmail.com>
Paul Donald <newtwen+github@gmail.com> Paul Donald <newtwen+github@gmail.com>
Pawel Palenica (qepasa) <pawelpalenica11@gmail.com> Pawel Palenica (qepasa) <pawelpalenica11@gmail.com>
Paweł Rozlach <vespian@users.noreply.github.com>
perewa <cavalcante.ten@gmail.com> perewa <cavalcante.ten@gmail.com>
Peter Badida <KeyWeeUsr@users.noreply.github.com> Peter Badida <KeyWeeUsr@users.noreply.github.com>
Peter Dave Hello <hsu@peterdavehello.org> Peter Dave Hello <hsu@peterdavehello.org>
@@ -255,16 +293,20 @@ Phani Rithvij <phanirithvij2000@gmail.com>
Phil Davis <phil.davis@inf.org> Phil Davis <phil.davis@inf.org>
Philippe Schommers (filoozoom) <philippe@schommers.be> Philippe Schommers (filoozoom) <philippe@schommers.be>
Phill Luby (pluby) <phill.luby@newredo.com> Phill Luby (pluby) <phill.luby@newredo.com>
Pier Paolo Ramon <ramonpierre@gmail.com>
Piotr Bejda (piobpl) <piotrb10@gmail.com> Piotr Bejda (piobpl) <piotrb10@gmail.com>
polyfloyd <polyfloyd@users.noreply.github.com> polyfloyd <polyfloyd@users.noreply.github.com>
Pramodh KP (pramodhkp) <pramodh.p@directi.com> <1507241+pramodhkp@users.noreply.github.com>
pullmerge <166967364+pullmerge@users.noreply.github.com> pullmerge <166967364+pullmerge@users.noreply.github.com>
Quentin Hibon <qh.public@yahoo.com> Quentin Hibon <qh.public@yahoo.com>
Rahmi Pruitt <rjpruitt16@gmail.com> Rahmi Pruitt <rjpruitt16@gmail.com>
red_led <red-led@users.noreply.github.com> red_led <red-led@users.noreply.github.com>
Richard Hartmann <RichiH@users.noreply.github.com>
Robert Carosi (nov1n) <robert@carosi.nl> Robert Carosi (nov1n) <robert@carosi.nl>
Roberto Santalla <roobre@users.noreply.github.com> Roberto Santalla <roobre@users.noreply.github.com>
Robin Schoonover <robin@cornhooves.org> Robin Schoonover <robin@cornhooves.org>
Roman Zaynetdinov (zaynetro) <romanznet@gmail.com> Roman Zaynetdinov (zaynetro) <romanznet@gmail.com>
Ross Smith II (rasa) <ross@smithii.com>
rubenbe <github-com-00ff86@vandamme.email> rubenbe <github-com-00ff86@vandamme.email>
Ruslan Yevdokymov <38809160+ruslanye@users.noreply.github.com> Ruslan Yevdokymov <38809160+ruslanye@users.noreply.github.com>
Ryan Qian <i@bitbili.net> Ryan Qian <i@bitbili.net>
@@ -276,14 +318,18 @@ Sergey Mishin (ralder) <ralder@yandex.ru>
Sertonix <83883937+Sertonix@users.noreply.github.com> Sertonix <83883937+Sertonix@users.noreply.github.com>
Severin von Wnuck-Lipinski <ss7@live.de> Severin von Wnuck-Lipinski <ss7@live.de>
Shaarad Dalvi <60266155+shaaraddalvi@users.noreply.github.com> <shdalv@microsoft.com> Shaarad Dalvi <60266155+shaaraddalvi@users.noreply.github.com> <shdalv@microsoft.com>
Simon Frei (imsodin) <freisim93@gmail.com>
Simon Mwepu <simonmwepu@gmail.com> Simon Mwepu <simonmwepu@gmail.com>
Simon Pickup <simon@pickupinfinity.com> Simon Pickup <simon@pickupinfinity.com>
Sly_tom_cat <slytomcat@mail.ru> Sly_tom_cat <slytomcat@mail.ru>
Sonu Kumar Saw <31889738+dev-saw99@users.noreply.github.com> Sonu Kumar Saw <31889738+dev-saw99@users.noreply.github.com>
Stefan Kuntz (Stefan-Code) <stefan.github@gmail.com> <Stefan.github@gmail.com> Stefan Kuntz (Stefan-Code) <stefan.github@gmail.com> <Stefan.github@gmail.com>
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org> <stefan@rumpelsepp.org>
Steven Eckhoff <steven.eckhoff.opensource@gmail.com> Steven Eckhoff <steven.eckhoff.opensource@gmail.com>
Suhas Gundimeda (snugghash) <suhas.gundimeda@gmail.com> <snugghash@gmail.com> Suhas Gundimeda (snugghash) <suhas.gundimeda@gmail.com> <snugghash@gmail.com>
Sven Bachmann <dev@mcbachmann.de> Sven Bachmann <dev@mcbachmann.de>
Syncthing Automation <automation@syncthing.net>
Syncthing Release Automation <release@syncthing.net>
Sébastien WENSKE <sebastien@wenske.fr> Sébastien WENSKE <sebastien@wenske.fr>
Taylor Khan (nelsonkhan) <nelsonkhan@gmail.com> Taylor Khan (nelsonkhan) <nelsonkhan@gmail.com>
Terrance <git@terrance.allofti.me> Terrance <git@terrance.allofti.me>
@@ -292,11 +338,15 @@ Thomas <9749173+uhthomas@users.noreply.github.com>
Thomas Hipp <thomashipp@gmail.com> Thomas Hipp <thomashipp@gmail.com>
Tim Abell (timabell) <tim@timwise.co.uk> Tim Abell (timabell) <tim@timwise.co.uk>
Tim Howes (timhowes) <timhowes@berkeley.edu> Tim Howes (timhowes) <timhowes@berkeley.edu>
Tim Nordenfur <tim@gurka.se>
Tobias Frölich <40638719+tobifroe@users.noreply.github.com> Tobias Frölich <40638719+tobifroe@users.noreply.github.com>
Tobias Klauser <tobias.klauser@gmail.com> Tobias Klauser <tobias.klauser@gmail.com>
Tobias Nygren (tnn2) <tnn@nygren.pp.se> Tobias Nygren (tnn2) <tnn@nygren.pp.se>
Tobias Tom (tobiastom) <t.tom@succont.de> Tobias Tom (tobiastom) <t.tom@succont.de>
Tom Jakubowski <tom@crystae.net> Tom Jakubowski <tom@crystae.net>
Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com> <twilczynski@naver.com>
Tommy Thorn <tommy-github-email@thorn.ws>
Tommy van der Vorst <tommy-github@pixelspark.nl> <tommy@pixelspark.nl>
Tully Robinson (tojrobinson) <tully@tojr.org> Tully Robinson (tojrobinson) <tully@tojr.org>
Tyler Brazier (tylerbrazier) <tyler@tylerbrazier.com> Tyler Brazier (tylerbrazier) <tyler@tylerbrazier.com>
Tyler Kropp <kropptyler@gmail.com> Tyler Kropp <kropptyler@gmail.com>
@@ -313,10 +363,10 @@ WangXi <xib1102@icloud.com>
Will Rouesnel <wrouesnel@wrouesnel.com> Will Rouesnel <wrouesnel@wrouesnel.com>
William A. Kennington III (wkennington) <william@wkennington.com> William A. Kennington III (wkennington) <william@wkennington.com>
wouter bolsterlee <wouter@bolsterl.ee> wouter bolsterlee <wouter@bolsterl.ee>
Wulf Weich (wweich) <wweich@users.noreply.github.com> <wweich@gmx.de> <wulf@weich-kr.de>
xarx00 <xarx00@users.noreply.github.com> xarx00 <xarx00@users.noreply.github.com>
Xavier O. (damajor) <damajor@gmail.com> Xavier O. (damajor) <damajor@gmail.com>
xjtdy888 (xjtdy888) <xjtdy888@163.com> <xjtdy888@gmail.com> xjtdy888 (xjtdy888) <xjtdy888@163.com>
Yannic A. (eipiminus1) <eipiminusone+github@gmail.com> <eipiminus1@users.noreply.github.com> Yannic A. (eipiminus1) <eipiminusone+github@gmail.com> <eipiminus1@users.noreply.github.com>
yparitcher <y@paritcher.com>
佛跳墙 <daoquan@qq.com> 佛跳墙 <daoquan@qq.com>
落心 <luoxin.ttt@gmail.com> 落心 <luoxin.ttt@gmail.com>
+61 -12
View File
@@ -58,6 +58,7 @@ var (
timeout = "120s" timeout = "120s"
longTimeout = "600s" longTimeout = "600s"
numVersions = 5 numVersions = 5
withNextGenGUI = os.Getenv("BUILD_NEXT_GEN_GUI") != ""
) )
type target struct { type target struct {
@@ -288,10 +289,10 @@ func runCommand(cmd string, target target) {
build(target, tags) build(target, tags)
case "test": case "test":
test(strings.Fields(extraTags), "github.com/syncthing/syncthing/internal/...", "github.com/syncthing/syncthing/lib/...", "github.com/syncthing/syncthing/cmd/...") test(strings.Fields(extraTags), "github.com/syncthing/syncthing/lib/...", "github.com/syncthing/syncthing/cmd/...")
case "bench": case "bench":
bench(strings.Fields(extraTags), "github.com/syncthing/syncthing/internal/...", "github.com/syncthing/syncthing/lib/...", "github.com/syncthing/syncthing/cmd/...") bench(strings.Fields(extraTags), "github.com/syncthing/syncthing/lib/...", "github.com/syncthing/syncthing/cmd/...")
case "integration": case "integration":
integration(false) integration(false)
@@ -379,6 +380,7 @@ func parseFlags() {
flag.IntVar(&numVersions, "num-versions", numVersions, "Number of versions for changelog command") flag.IntVar(&numVersions, "num-versions", numVersions, "Number of versions for changelog command")
flag.StringVar(&run, "run", "", "Specify which tests to run") flag.StringVar(&run, "run", "", "Specify which tests to run")
flag.StringVar(&benchRun, "bench", "", "Specify which benchmarks to run") flag.StringVar(&benchRun, "bench", "", "Specify which benchmarks to run")
flag.BoolVar(&withNextGenGUI, "with-next-gen-gui", withNextGenGUI, "Also build 'newgui'")
flag.StringVar(&buildOut, "build-out", "", "Set the '-o' value for 'go build'") flag.StringVar(&buildOut, "build-out", "", "Set the '-o' value for 'go build'")
flag.Parse() flag.Parse()
} }
@@ -451,6 +453,10 @@ func benchArgs() []string {
} }
func install(target target, tags []string) { func install(target target, tags []string) {
if (target.name == "syncthing" || target.name == "") && !withNextGenGUI {
log.Println("Notice: Next generation GUI will not be built; see --with-next-gen-gui.")
}
lazyRebuildAssets() lazyRebuildAssets()
tags = append(target.tags, tags...) tags = append(target.tags, tags...)
@@ -474,12 +480,16 @@ func install(target target, tags []string) {
defer shouldCleanupSyso(sysoPath) defer shouldCleanupSyso(sysoPath)
} }
args := []string{"install"} args := []string{"install", "-v"}
args = appendParameters(args, tags, target.buildPkgs...) args = appendParameters(args, tags, target.buildPkgs...)
runPrint(goCmd, args...) runPrint(goCmd, args...)
} }
func build(target target, tags []string) { func build(target target, tags []string) {
if (target.name == "syncthing" || target.name == "") && !withNextGenGUI {
log.Println("Notice: Next generation GUI will not be built; see --with-next-gen-gui.")
}
lazyRebuildAssets() lazyRebuildAssets()
tags = append(target.tags, tags...) tags = append(target.tags, tags...)
@@ -502,7 +512,7 @@ func build(target target, tags []string) {
defer shouldCleanupSyso(sysoPath) defer shouldCleanupSyso(sysoPath)
} }
args := []string{"build"} args := []string{"build", "-v"}
if buildOut != "" { if buildOut != "" {
args = append(args, "-o", buildOut) args = append(args, "-o", buildOut)
} }
@@ -514,6 +524,13 @@ func setBuildEnvVars() {
os.Setenv("GOOS", goos) os.Setenv("GOOS", goos)
os.Setenv("GOARCH", goarch) os.Setenv("GOARCH", goarch)
os.Setenv("CC", cc) os.Setenv("CC", cc)
if os.Getenv("CGO_ENABLED") == "" {
switch goos {
case "darwin", "solaris":
default:
os.Setenv("CGO_ENABLED", "0")
}
}
} }
func appendParameters(args []string, tags []string, pkgs ...string) []string { func appendParameters(args []string, tags []string, pkgs ...string) []string {
@@ -732,9 +749,12 @@ func shouldBuildSyso(dir string) (string, error) {
sysoPath := filepath.Join(dir, "cmd", "syncthing", "resource.syso") sysoPath := filepath.Join(dir, "cmd", "syncthing", "resource.syso")
// See https://github.com/josephspurrier/goversioninfo#command-line-flags // See https://github.com/josephspurrier/goversioninfo#command-line-flags
arm := strings.HasPrefix(goarch, "arm") armOption := ""
a64 := strings.Contains(goarch, "64") if strings.Contains(goarch, "arm") {
if _, err := runError("goversioninfo", "-o", sysoPath, fmt.Sprintf("-arm=%v", arm), fmt.Sprintf("-64=%v", a64)); err != nil { armOption = "-arm=true"
}
if _, err := runError("goversioninfo", "-o", sysoPath, armOption); err != nil {
return "", errors.New("failed to create " + sysoPath + ": " + err.Error()) return "", errors.New("failed to create " + sysoPath + ": " + err.Error())
} }
@@ -806,11 +826,43 @@ func lazyRebuildAssets() {
shouldRebuild := shouldRebuildAssets("lib/api/auto/gui.files.go", "gui") || shouldRebuild := shouldRebuildAssets("lib/api/auto/gui.files.go", "gui") ||
shouldRebuildAssets("cmd/infra/strelaypoolsrv/auto/gui.files.go", "cmd/infra/strelaypoolsrv/gui") shouldRebuildAssets("cmd/infra/strelaypoolsrv/auto/gui.files.go", "cmd/infra/strelaypoolsrv/gui")
if withNextGenGUI {
shouldRebuild = buildNextGenGUI() || shouldRebuild
}
if shouldRebuild { if shouldRebuild {
rebuildAssets() rebuildAssets()
} }
} }
func buildNextGenGUI() bool {
// Check if we need to run the npm process, and if so also set the flag
// to rebuild Go assets afterwards. The index.html is regenerated every
// time by the build process. This assumes the new GUI ends up in
// next-gen-gui/dist/next-gen-gui.
if !shouldRebuildAssets("gui/next-gen-gui/index.html", "next-gen-gui") {
// The GUI is up to date.
return false
}
runPrintInDir("next-gen-gui", "npm", "install")
runPrintInDir("next-gen-gui", "npm", "run", "build", "--", "--prod", "--subresource-integrity")
rmr("gui/tech-ui")
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, 0o644); err != nil {
fmt.Println("copy:", err)
os.Exit(1)
}
}
return true
}
func shouldRebuildAssets(target, srcdir string) bool { func shouldRebuildAssets(target, srcdir string) bool {
info, err := os.Stat(target) info, err := os.Stat(target)
if err != nil { if err != nil {
@@ -870,6 +922,7 @@ func testmocks() {
"github.com/syncthing/syncthing/lib/connections", "github.com/syncthing/syncthing/lib/connections",
"github.com/syncthing/syncthing/lib/discover", "github.com/syncthing/syncthing/lib/discover",
"github.com/syncthing/syncthing/lib/events", "github.com/syncthing/syncthing/lib/events",
"github.com/syncthing/syncthing/lib/logger",
"github.com/syncthing/syncthing/lib/model", "github.com/syncthing/syncthing/lib/model",
"github.com/syncthing/syncthing/lib/protocol", "github.com/syncthing/syncthing/lib/protocol",
} }
@@ -900,7 +953,6 @@ func weblate() {
func ldflags(tags []string) string { func ldflags(tags []string) string {
b := new(strings.Builder) b := new(strings.Builder)
b.WriteString("-w") b.WriteString("-w")
b.WriteString(" -buildid=")
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Version=%s", version) fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Version=%s", version)
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Stamp=%d", buildStamp()) fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Stamp=%d", buildStamp())
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.User=%s", buildUser()) fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.User=%s", buildUser())
@@ -922,9 +974,6 @@ func rmr(paths ...string) {
} }
func getReleaseVersion() (string, error) { func getReleaseVersion() (string, error) {
if ver := os.Getenv("VERSION"); ver != "" {
return strings.TrimSpace(ver), nil
}
bs, err := os.ReadFile("RELEASE") bs, err := os.ReadFile("RELEASE")
if err != nil { if err != nil {
return "", err return "", err
@@ -969,7 +1018,7 @@ func getGitVersion() (string, error) {
} }
func getVersion() string { func getVersion() string {
// First try for a RELEASE file or $VERSION env var, // First try for a RELEASE file,
if ver, err := getReleaseVersion(); err == nil { if ver, err := getReleaseVersion(); err == nil {
return ver return ver
} }
+1 -1
View File
@@ -72,7 +72,7 @@ func main() {
if *standardBlocks || blockSize < protocol.MinBlockSize { if *standardBlocks || blockSize < protocol.MinBlockSize {
blockSize = protocol.BlockSize(fi.Size()) blockSize = protocol.BlockSize(fi.Size())
} }
bs, err := scanner.Blocks(context.TODO(), fd, blockSize, fi.Size(), nil) bs, err := scanner.Blocks(context.TODO(), fd, blockSize, fi.Size(), nil, true)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
+3 -3
View File
@@ -44,7 +44,7 @@ type cli struct {
SentryQueue int `help:"Maximum number of reports to queue for sending to Sentry" default:"64" env:"SENTRY_QUEUE"` SentryQueue int `help:"Maximum number of reports to queue for sending to Sentry" default:"64" env:"SENTRY_QUEUE"`
DiskQueue int `help:"Maximum number of reports to queue for writing to disk" default:"64" env:"DISK_QUEUE"` DiskQueue int `help:"Maximum number of reports to queue for writing to disk" default:"64" env:"DISK_QUEUE"`
MetricsListen string `help:"HTTP listen address for metrics" default:":8081" env:"METRICS_LISTEN_ADDRESS"` MetricsListen string `help:"HTTP listen address for metrics" default:":8081" env:"METRICS_LISTEN_ADDRESS"`
IgnorePatterns string `help:"File containing ignore patterns (regexp)" env:"IGNORE_PATTERNS" type:"existingfile"` IngorePatterns string `help:"File containing ignore patterns (regexp)" env:"IGNORE_PATTERNS" type:"existingfile"`
} }
func main() { func main() {
@@ -68,9 +68,9 @@ func main() {
go ss.Serve(context.Background()) go ss.Serve(context.Background())
var ip *ignorePatterns var ip *ignorePatterns
if params.IgnorePatterns != "" { if params.IngorePatterns != "" {
var err error var err error
ip, err = loadIgnorePatterns(params.IgnorePatterns) ip, err = loadIgnorePatterns(params.IngorePatterns)
if err != nil { if err != nil {
log.Fatalf("Failed to load ignore patterns: %v", err) log.Fatalf("Failed to load ignore patterns: %v", err)
} }
+3 -3
View File
@@ -17,7 +17,6 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"sync"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -32,6 +31,7 @@ import (
"github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand" "github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/relay/client" "github.com/syncthing/syncthing/lib/relay/client"
"github.com/syncthing/syncthing/lib/sync"
"github.com/syncthing/syncthing/lib/tlsutil" "github.com/syncthing/syncthing/lib/tlsutil"
) )
@@ -115,7 +115,7 @@ var (
requests chan request requests chan request
mut sync.RWMutex mut = sync.NewRWMutex()
knownRelays = make([]*relay, 0) knownRelays = make([]*relay, 0)
permanentRelays = make([]*relay, 0) permanentRelays = make([]*relay, 0)
evictionTimers = make(map[string]*time.Timer) evictionTimers = make(map[string]*time.Timer)
@@ -620,7 +620,7 @@ func createTestCertificate() tls.Certificate {
} }
certFile, keyFile := filepath.Join(tmpDir, "cert.pem"), filepath.Join(tmpDir, "key.pem") certFile, keyFile := filepath.Join(tmpDir, "cert.pem"), filepath.Join(tmpDir, "key.pem")
cert, err := tlsutil.NewCertificate(certFile, keyFile, "relaypoolsrv", 20*365, false) cert, err := tlsutil.NewCertificate(certFile, keyFile, "relaypoolsrv", 20*365)
if err != nil { if err != nil {
log.Fatalln("Failed to create test X509 key pair:", err) log.Fatalln("Failed to create test X509 key pair:", err)
} }
+3
View File
@@ -13,6 +13,7 @@ import (
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
"strings" "strings"
"sync"
"testing" "testing"
) )
@@ -27,6 +28,8 @@ func init() {
{URL: "known2"}, {URL: "known2"},
{URL: "known3"}, {URL: "known3"},
} }
mut = new(sync.RWMutex)
} }
// Regression test: handleGetRequest should not modify permanentRelays. // Regression test: handleGetRequest should not modify permanentRelays.
+3 -3
View File
@@ -6,10 +6,10 @@ import (
"encoding/json" "encoding/json"
"net" "net"
"net/http" "net/http"
"sync"
"time" "time"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/syncthing/syncthing/lib/sync"
) )
var ( var (
@@ -104,7 +104,7 @@ func refreshStats() {
mut.RUnlock() mut.RUnlock()
now := time.Now() now := time.Now()
var wg sync.WaitGroup wg := sync.NewWaitGroup()
results := make(chan statsFetchResult, len(relays)) results := make(chan statsFetchResult, len(relays))
for _, rel := range relays { for _, rel := range relays {
@@ -173,7 +173,7 @@ func fetchStats(relay *relay) *stats {
var stats stats var stats stats
if err := json.NewDecoder(response.Body).Decode(&stats); err != nil { if json.NewDecoder(response.Body).Decode(&stats); err != nil {
return nil return nil
} }
return &stats return &stats
+7 -8
View File
@@ -24,7 +24,6 @@ import (
"github.com/alecthomas/kong" "github.com/alecthomas/kong"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/syncthing/syncthing/internal/slogutil"
_ "github.com/syncthing/syncthing/lib/automaxprocs" _ "github.com/syncthing/syncthing/lib/automaxprocs"
"github.com/syncthing/syncthing/lib/httpcache" "github.com/syncthing/syncthing/lib/httpcache"
"github.com/syncthing/syncthing/lib/upgrade" "github.com/syncthing/syncthing/lib/upgrade"
@@ -59,10 +58,10 @@ func server(params *cli) error {
if err != nil { if err != nil {
return fmt.Errorf("metrics: %w", err) return fmt.Errorf("metrics: %w", err)
} }
slog.Info("Metrics listener started", slogutil.Address(params.MetricsListen)) slog.Info("Metrics listener started", "addr", params.MetricsListen)
go func() { go func() {
if err := http.Serve(metricsListen, mux); err != nil { if err := http.Serve(metricsListen, mux); err != nil {
slog.Warn("Metrics server returned", slogutil.Error(err)) slog.Warn("Metrics server returned", "error", err)
} }
}() }()
} }
@@ -76,9 +75,9 @@ func server(params *cli) error {
go func() { go func() {
for range time.NewTicker(params.CacheTime).C { for range time.NewTicker(params.CacheTime).C {
slog.Info("Refreshing cached releases", slogutil.URI(params.URL)) slog.Info("Refreshing cached releases", "url", params.URL)
if err := cache.Update(context.Background()); err != nil { if err := cache.Update(context.Background()); err != nil {
slog.Error("Failed to refresh cached releases", slogutil.URI(params.URL), slogutil.Error(err)) slog.Error("Failed to refresh cached releases", "url", params.URL, "error", err)
} }
} }
}() }()
@@ -110,7 +109,7 @@ func server(params *cli) error {
if err != nil { if err != nil {
return fmt.Errorf("listen: %w", err) return fmt.Errorf("listen: %w", err)
} }
slog.Info("Main listener started", slogutil.Address(params.Listen)) slog.Info("Main listener started", "addr", params.Listen)
return srv.Serve(srvListener) return srv.Serve(srvListener)
} }
@@ -138,7 +137,7 @@ func (p *githubReleases) serveReleases(w http.ResponseWriter, req *http.Request)
osv := req.Header.Get("Syncthing-Os-Version") osv := req.Header.Get("Syncthing-Os-Version")
if ua != "" && osv != "" { if ua != "" && osv != "" {
// We should determine the compatibility of the releases. // We should determine the compatibility of the releases.
rels = filterForCompatibility(rels, ua, osv) rels = filterForCompabitility(rels, ua, osv)
} else { } else {
metricFilterCalls.WithLabelValues("no-ua-or-osversion").Inc() metricFilterCalls.WithLabelValues("no-ua-or-osversion").Inc()
} }
@@ -224,7 +223,7 @@ func filterForLatest(rels []upgrade.Release) []upgrade.Release {
var userAgentOSArchExp = regexp.MustCompile(`^syncthing.*\(.+ (\w+)-(\w+)\)$`) var userAgentOSArchExp = regexp.MustCompile(`^syncthing.*\(.+ (\w+)-(\w+)\)$`)
func filterForCompatibility(rels []upgrade.Release, ua, osv string) []upgrade.Release { func filterForCompabitility(rels []upgrade.Release, ua, osv string) []upgrade.Release {
osArch := userAgentOSArchExp.FindStringSubmatch(ua) osArch := userAgentOSArchExp.FindStringSubmatch(ua)
if len(osArch) != 3 { if len(osArch) != 3 {
metricFilterCalls.WithLabelValues("bad-os-arch").Inc() metricFilterCalls.WithLabelValues("bad-os-arch").Inc()
-15
View File
@@ -32,21 +32,6 @@ var (
Subsystem: "ursrv_v2", Subsystem: "ursrv_v2",
Name: "collect_seconds_last", Name: "collect_seconds_last",
}) })
metricsRecalcsTotal = promauto.NewCounter(prometheus.CounterOpts{
Namespace: "syncthing",
Subsystem: "ursrv_v2",
Name: "recalcs_total",
})
metricsRecalcSecondsTotal = promauto.NewCounter(prometheus.CounterOpts{
Namespace: "syncthing",
Subsystem: "ursrv_v2",
Name: "recalc_seconds_total",
})
metricsRecalcSecondsLast = promauto.NewGauge(prometheus.GaugeOpts{
Namespace: "syncthing",
Subsystem: "ursrv_v2",
Name: "recalc_seconds_last",
})
metricsWriteSecondsLast = promauto.NewGauge(prometheus.GaugeOpts{ metricsWriteSecondsLast = promauto.NewGauge(prometheus.GaugeOpts{
Namespace: "syncthing", Namespace: "syncthing",
Subsystem: "ursrv_v2", Subsystem: "ursrv_v2",
+23 -59
View File
@@ -7,8 +7,6 @@
package serve package serve
import ( import (
"context"
"log/slog"
"reflect" "reflect"
"slices" "slices"
"strconv" "strconv"
@@ -30,7 +28,7 @@ type metricsSet struct {
gaugeVecLabels map[string][]string gaugeVecLabels map[string][]string
summaries map[string]*metricSummary summaries map[string]*metricSummary
collectMut sync.RWMutex collectMut sync.Mutex
collectCutoff time.Duration collectCutoff time.Duration
} }
@@ -110,60 +108,6 @@ func nameConstLabels(name string) (string, prometheus.Labels) {
return name, m return name, m
} }
func (s *metricsSet) Serve(ctx context.Context) error {
s.recalc()
const recalcInterval = 5 * time.Minute
next := time.Until(time.Now().Truncate(recalcInterval).Add(recalcInterval))
recalcTimer := time.NewTimer(next)
defer recalcTimer.Stop()
for {
select {
case <-recalcTimer.C:
s.recalc()
next := time.Until(time.Now().Truncate(recalcInterval).Add(recalcInterval))
recalcTimer.Reset(next)
case <-ctx.Done():
return ctx.Err()
}
}
}
func (s *metricsSet) recalc() {
s.collectMut.Lock()
defer s.collectMut.Unlock()
t0 := time.Now()
defer func() {
dur := time.Since(t0)
slog.Info("Metrics recalculated", "d", dur.String())
metricsRecalcSecondsLast.Set(dur.Seconds())
metricsRecalcSecondsTotal.Add(dur.Seconds())
metricsRecalcsTotal.Inc()
}()
for _, g := range s.gauges {
g.Set(0)
}
for _, g := range s.gaugeVecs {
g.Reset()
}
for _, g := range s.summaries {
g.Reset()
}
cutoff := time.Now().Add(s.collectCutoff)
s.srv.reports.Range(func(key string, r *contract.Report) bool {
if s.collectCutoff < 0 && r.Received.Before(cutoff) {
s.srv.reports.Delete(key)
return true
}
s.addReport(r)
return true
})
}
func (s *metricsSet) addReport(r *contract.Report) { func (s *metricsSet) addReport(r *contract.Report) {
gaugeVecs := make(map[string][]string) gaugeVecs := make(map[string][]string)
s.addReportStruct(reflect.ValueOf(r).Elem(), gaugeVecs) s.addReportStruct(reflect.ValueOf(r).Elem(), gaugeVecs)
@@ -254,8 +198,8 @@ func (s *metricsSet) Describe(c chan<- *prometheus.Desc) {
} }
func (s *metricsSet) Collect(c chan<- prometheus.Metric) { func (s *metricsSet) Collect(c chan<- prometheus.Metric) {
s.collectMut.RLock() s.collectMut.Lock()
defer s.collectMut.RUnlock() defer s.collectMut.Unlock()
t0 := time.Now() t0 := time.Now()
defer func() { defer func() {
@@ -265,6 +209,26 @@ func (s *metricsSet) Collect(c chan<- prometheus.Metric) {
metricsCollectsTotal.Inc() metricsCollectsTotal.Inc()
}() }()
for _, g := range s.gauges {
g.Set(0)
}
for _, g := range s.gaugeVecs {
g.Reset()
}
for _, g := range s.summaries {
g.Reset()
}
cutoff := time.Now().Add(s.collectCutoff)
s.srv.reports.Range(func(key string, r *contract.Report) bool {
if s.collectCutoff < 0 && r.Received.Before(cutoff) {
s.srv.reports.Delete(key)
return true
}
s.addReport(r)
return true
})
for _, g := range s.gauges { for _, g := range s.gauges {
c <- g c <- g
} }
+16 -37
View File
@@ -29,11 +29,9 @@ import (
"github.com/syncthing/syncthing/internal/blob" "github.com/syncthing/syncthing/internal/blob"
"github.com/syncthing/syncthing/internal/blob/azureblob" "github.com/syncthing/syncthing/internal/blob/azureblob"
"github.com/syncthing/syncthing/internal/blob/s3" "github.com/syncthing/syncthing/internal/blob/s3"
"github.com/syncthing/syncthing/internal/slogutil"
"github.com/syncthing/syncthing/lib/build" "github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/geoip" "github.com/syncthing/syncthing/lib/geoip"
"github.com/syncthing/syncthing/lib/ur/contract" "github.com/syncthing/syncthing/lib/ur/contract"
"github.com/thejerf/suture/v4"
) )
type CLI struct { type CLI struct {
@@ -106,23 +104,23 @@ func (cli *CLI) Run() error {
urListener, err := net.Listen("tcp", cli.Listen) urListener, err := net.Listen("tcp", cli.Listen)
if err != nil { if err != nil {
slog.Error("Failed to listen (usage reports)", slogutil.Error(err)) slog.Error("Failed to listen (usage reports)", "error", err)
return err return err
} }
slog.Info("Listening (usage reports)", slogutil.Address(urListener.Addr())) slog.Info("Listening (usage reports)", "address", urListener.Addr())
internalListener, err := net.Listen("tcp", cli.ListenInternal) internalListener, err := net.Listen("tcp", cli.ListenInternal)
if err != nil { if err != nil {
slog.Error("Failed to listen (internal)", slogutil.Error(err)) slog.Error("Failed to listen (internal)", "error", err)
return err return err
} }
slog.Info("Listening (internal)", slogutil.Address(internalListener.Addr())) slog.Info("Listening (internal)", "address", internalListener.Addr())
var geo *geoip.Provider var geo *geoip.Provider
if cli.GeoIPAccountID != 0 && cli.GeoIPLicenseKey != "" { if cli.GeoIPAccountID != 0 && cli.GeoIPLicenseKey != "" {
geo, err = geoip.NewGeoLite2CityProvider(context.Background(), cli.GeoIPAccountID, cli.GeoIPLicenseKey, os.TempDir()) geo, err = geoip.NewGeoLite2CityProvider(context.Background(), cli.GeoIPAccountID, cli.GeoIPLicenseKey, os.TempDir())
if err != nil { if err != nil {
slog.Error("Failed to load GeoIP", slogutil.Error(err)) slog.Error("Failed to load GeoIP", "error", err)
return err return err
} }
go geo.Serve(context.TODO()) go geo.Serve(context.TODO())
@@ -134,20 +132,20 @@ func (cli *CLI) Run() error {
if cli.S3Endpoint != "" { if cli.S3Endpoint != "" {
blobs, err = s3.NewSession(cli.S3Endpoint, cli.S3Region, cli.S3Bucket, cli.S3AccessKeyID, cli.S3SecretKey) blobs, err = s3.NewSession(cli.S3Endpoint, cli.S3Region, cli.S3Bucket, cli.S3AccessKeyID, cli.S3SecretKey)
if err != nil { if err != nil {
slog.Error("Failed to create S3 session", slogutil.Error(err)) slog.Error("Failed to create S3 session", "error", err)
return err return err
} }
} else if cli.AzureBlobAccount != "" { } else if cli.AzureBlobAccount != "" {
blobs, err = azureblob.NewBlobStore(cli.AzureBlobAccount, cli.AzureBlobKey, cli.AzureBlobContainer) blobs, err = azureblob.NewBlobStore(cli.AzureBlobAccount, cli.AzureBlobKey, cli.AzureBlobContainer)
if err != nil { if err != nil {
slog.Error("Failed to create Azure blob store", slogutil.Error(err)) slog.Error("Failed to create Azure blob store", "error", err)
return err return err
} }
} }
if _, err := os.Stat(cli.DumpFile); err != nil && blobs != nil { if _, err := os.Stat(cli.DumpFile); err != nil && blobs != nil {
if err := cli.downloadDumpFile(blobs); err != nil { if err := cli.downloadDumpFile(blobs); err != nil {
slog.Error("Failed to download dump file", slogutil.Error(err)) slog.Error("Failed to download dump file", "error", err)
} }
} }
@@ -169,7 +167,7 @@ func (cli *CLI) Run() error {
go func() { go func() {
for range time.Tick(cli.DumpInterval) { for range time.Tick(cli.DumpInterval) {
if err := cli.saveDumpFile(srv, blobs); err != nil { if err := cli.saveDumpFile(srv, blobs); err != nil {
slog.Error("Failed to write dump file", slogutil.Error(err)) slog.Error("Failed to write dump file", "error", err)
} }
} }
}() }()
@@ -188,12 +186,7 @@ func (cli *CLI) Run() error {
// New external metrics endpoint accepts reports from clients and serves // New external metrics endpoint accepts reports from clients and serves
// aggregated usage reporting metrics. // aggregated usage reporting metrics.
main := suture.NewSimple("main")
main.ServeBackground(context.Background())
ms := newMetricsSet(srv) ms := newMetricsSet(srv)
main.Add(ms)
reg := prometheus.NewRegistry() reg := prometheus.NewRegistry()
reg.MustRegister(ms) reg.MustRegister(ms)
@@ -204,7 +197,7 @@ func (cli *CLI) Run() error {
metricsSrv := http.Server{ metricsSrv := http.Server{
ReadTimeout: 5 * time.Second, ReadTimeout: 5 * time.Second,
WriteTimeout: 60 * time.Second, WriteTimeout: 15 * time.Second,
Handler: mux, Handler: mux,
} }
@@ -233,11 +226,6 @@ func (cli *CLI) downloadDumpFile(blobs blob.Store) error {
} }
func (cli *CLI) saveDumpFile(srv *server, blobs blob.Store) error { func (cli *CLI) saveDumpFile(srv *server, blobs blob.Store) error {
t0 := time.Now()
defer func() {
metricsWriteSecondsLast.Set(float64(time.Since(t0)))
}()
fd, err := os.Create(cli.DumpFile + ".tmp") fd, err := os.Create(cli.DumpFile + ".tmp")
if err != nil { if err != nil {
return fmt.Errorf("creating dump file: %w", err) return fmt.Errorf("creating dump file: %w", err)
@@ -256,10 +244,9 @@ func (cli *CLI) saveDumpFile(srv *server, blobs blob.Store) error {
if err := os.Rename(cli.DumpFile+".tmp", cli.DumpFile); err != nil { if err := os.Rename(cli.DumpFile+".tmp", cli.DumpFile); err != nil {
return fmt.Errorf("renaming dump file: %w", err) return fmt.Errorf("renaming dump file: %w", err)
} }
slog.Info("Dump file saved", "d", time.Since(t0).String()) slog.Info("Dump file saved")
if blobs != nil { if blobs != nil {
t1 := time.Now()
key := fmt.Sprintf("reports-%s.jsons.gz", time.Now().UTC().Format("2006-01-02")) key := fmt.Sprintf("reports-%s.jsons.gz", time.Now().UTC().Format("2006-01-02"))
fd, err := os.Open(cli.DumpFile) fd, err := os.Open(cli.DumpFile)
if err != nil { if err != nil {
@@ -269,7 +256,7 @@ func (cli *CLI) saveDumpFile(srv *server, blobs blob.Store) error {
return fmt.Errorf("uploading dump file: %w", err) return fmt.Errorf("uploading dump file: %w", err)
} }
_ = fd.Close() _ = fd.Close()
slog.Info("Dump file uploaded", "d", time.Since(t1).String()) slog.Info("Dump file uploaded")
} }
return nil return nil
@@ -320,7 +307,7 @@ func (s *server) handleNewData(w http.ResponseWriter, r *http.Request) {
lr := &io.LimitedReader{R: r.Body, N: 40 * 1024} lr := &io.LimitedReader{R: r.Body, N: 40 * 1024}
bs, _ := io.ReadAll(lr) bs, _ := io.ReadAll(lr)
if err := json.Unmarshal(bs, &rep); err != nil { if err := json.Unmarshal(bs, &rep); err != nil {
log.Error("Failed to decode JSON", slogutil.Error(err)) log.Error("Failed to decode JSON", "error", err)
http.Error(w, "JSON Decode Error", http.StatusInternalServerError) http.Error(w, "JSON Decode Error", http.StatusInternalServerError)
return return
} }
@@ -330,7 +317,7 @@ func (s *server) handleNewData(w http.ResponseWriter, r *http.Request) {
rep.Address = addr rep.Address = addr
if err := rep.Validate(); err != nil { if err := rep.Validate(); err != nil {
log.Error("Failed to validate report", slogutil.Error(err)) log.Error("Failed to validate report", "error", err)
http.Error(w, "Validation Error", http.StatusInternalServerError) http.Error(w, "Validation Error", http.StatusInternalServerError)
return return
} }
@@ -381,13 +368,6 @@ func (s *server) addReport(rep *contract.Report) bool {
rep.DistOS = rep.OS rep.DistOS = rep.OS
rep.DistArch = rep.Arch rep.DistArch = rep.Arch
if strings.HasPrefix(rep.Version, "v2.") {
rep.Database.ModernCSQLite = strings.Contains(rep.LongVersion, "modernc-sqlite")
rep.Database.MattnSQLite = !rep.Database.ModernCSQLite
} else {
rep.Database.LevelDB = true
}
_, loaded := s.reports.LoadAndStore(rep.UniqueID, rep) _, loaded := s.reports.LoadAndStore(rep.UniqueID, rep)
return loaded return loaded
} }
@@ -407,7 +387,6 @@ func (s *server) save(w io.Writer) error {
} }
func (s *server) load(r io.Reader) { func (s *server) load(r io.Reader) {
t0 := time.Now()
dec := json.NewDecoder(r) dec := json.NewDecoder(r)
s.reports.Clear() s.reports.Clear()
for { for {
@@ -415,12 +394,12 @@ func (s *server) load(r io.Reader) {
if err := dec.Decode(&rep); errors.Is(err, io.EOF) { if err := dec.Decode(&rep); errors.Is(err, io.EOF) {
break break
} else if err != nil { } else if err != nil {
slog.Error("Failed to load record", slogutil.Error(err)) slog.Error("Failed to load record", "error", err)
break break
} }
s.addReport(&rep) s.addReport(&rep)
} }
slog.Info("Loaded reports", "count", s.reports.Size(), "d", time.Since(t0).String()) slog.Info("Loaded reports", "count", s.reports.Size())
} }
var ( var (
+1 -1
View File
@@ -115,7 +115,7 @@ func BenchmarkAPIRequests(b *testing.B) {
srv := httptest.NewServer(http.HandlerFunc(api.handler)) srv := httptest.NewServer(http.HandlerFunc(api.handler))
kf := b.TempDir() + "/cert" kf := b.TempDir() + "/cert"
crt, err := tlsutil.NewCertificate(kf+".crt", kf+".key", "localhost", 7, true) crt, err := tlsutil.NewCertificate(kf+".crt", kf+".key", "localhost", 7)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
+1 -1
View File
@@ -107,7 +107,7 @@ func main() {
cert, err = tls.LoadX509KeyPair(cli.Cert, cli.Key) cert, err = tls.LoadX509KeyPair(cli.Cert, cli.Key)
if os.IsNotExist(err) { if os.IsNotExist(err) {
log.Println("Failed to load keypair. Generating one, this might take a while...") log.Println("Failed to load keypair. Generating one, this might take a while...")
cert, err = tlsutil.NewCertificate(cli.Cert, cli.Key, "stdiscosrv", 20*365, false) cert, err = tlsutil.NewCertificate(cli.Cert, cli.Key, "stdiscosrv", 20*365)
if err != nil { if err != nil {
log.Fatalln("Failed to generate X509 key pair:", err) log.Fatalln("Failed to generate X509 key pair:", err)
} }
+1 -1
View File
@@ -157,7 +157,7 @@ func main() {
cert, err := tls.LoadX509KeyPair(certFile, keyFile) cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil { if err != nil {
log.Println("Failed to load keypair. Generating one, this might take a while...") log.Println("Failed to load keypair. Generating one, this might take a while...")
cert, err = tlsutil.NewCertificate(certFile, keyFile, "strelaysrv", 20*365, false) cert, err = tlsutil.NewCertificate(certFile, keyFile, "strelaysrv", 20*365)
if err != nil { if err != nil {
log.Fatalln("Failed to generate X509 key pair:", err) log.Fatalln("Failed to generate X509 key pair:", err)
} }
+2 -5
View File
@@ -8,14 +8,11 @@ package main
import ( import (
"fmt" "fmt"
"log/slog"
"os" "os"
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"syscall" "syscall"
"time" "time"
"github.com/syncthing/syncthing/internal/slogutil"
) )
func startBlockProfiler() { func startBlockProfiler() {
@@ -23,10 +20,10 @@ func startBlockProfiler() {
if profiler == nil { if profiler == nil {
panic("Couldn't find block profiler") panic("Couldn't find block profiler")
} }
slog.Debug("Starting block profiling") l.Debugln("Starting block profiling")
go func() { go func() {
err := saveBlockingProfiles(profiler) // Only returns on error err := saveBlockingProfiles(profiler) // Only returns on error
slog.Error("Block profiler failed", slogutil.Error(err)) l.Warnln("Block profiler failed:", err)
panic("Block profiler failed") panic("Block profiler failed")
}() }()
} }
+1
View File
@@ -41,4 +41,5 @@ func (p *profileCommand) Run(ctx Context) error {
type debugCommand struct { type debugCommand struct {
File fileCommand `cmd:"" help:"Show information about a file (or directory/symlink)"` File fileCommand `cmd:"" help:"Show information about a file (or directory/symlink)"`
Profile profileCommand `cmd:"" help:"Save a profile to help figuring out what Syncthing does"` Profile profileCommand `cmd:"" help:"Save a profile to help figuring out what Syncthing does"`
Index indexCommand `cmd:"" help:"Show information about the index (database)"`
} }
+32
View File
@@ -0,0 +1,32 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package cli
import (
"github.com/alecthomas/kong"
)
type indexCommand struct {
Dump struct{} `cmd:"" help:"Print the entire db"`
DumpSize struct{} `cmd:"" help:"Print the db size of different categories of information"`
Check struct{} `cmd:"" help:"Check the database for inconsistencies"`
Account struct{} `cmd:"" help:"Print key and value size statistics per key type"`
}
func (*indexCommand) Run(kongCtx *kong.Context) error {
switch kongCtx.Selected().Name {
case "dump":
return indexDump()
case "dump-size":
return indexDumpSize()
case "check":
return indexCheck()
case "account":
return indexAccount()
}
return nil
}
+62
View File
@@ -0,0 +1,62 @@
// Copyright (C) 2020 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package cli
import (
"fmt"
"os"
"text/tabwriter"
)
// indexAccount prints key and data size statistics per class
func indexAccount() error {
ldb, err := getDB()
if err != nil {
return err
}
it, err := ldb.NewPrefixIterator(nil)
if err != nil {
return err
}
var ksizes [256]int
var dsizes [256]int
var counts [256]int
var max [256]int
for it.Next() {
key := it.Key()
t := key[0]
ds := len(it.Value())
ks := len(key)
s := ks + ds
counts[t]++
ksizes[t] += ks
dsizes[t] += ds
if s > max[t] {
max[t] = s
}
}
tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', tabwriter.AlignRight)
toti, totds, totks := 0, 0, 0
for t := range ksizes {
if ksizes[t] > 0 {
// yes metric kilobytes 🤘
fmt.Fprintf(tw, "0x%02x:\t%d items,\t%d KB keys +\t%d KB data,\t%d B +\t%d B avg,\t%d B max\t\n", t, counts[t], ksizes[t]/1000, dsizes[t]/1000, ksizes[t]/counts[t], dsizes[t]/counts[t], max[t])
toti += counts[t]
totds += dsizes[t]
totks += ksizes[t]
}
}
fmt.Fprintf(tw, "Total\t%d items,\t%d KB keys +\t%d KB data.\t\n", toti, totks/1000, totds/1000)
tw.Flush()
return nil
}
+162
View File
@@ -0,0 +1,162 @@
// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package cli
import (
"encoding/binary"
"fmt"
"time"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/bep"
"github.com/syncthing/syncthing/internal/gen/dbproto"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/protocol"
)
func indexDump() error {
ldb, err := getDB()
if err != nil {
return err
}
it, err := ldb.NewPrefixIterator(nil)
if err != nil {
return err
}
for it.Next() {
key := it.Key()
switch key[0] {
case db.KeyTypeDevice:
folder := binary.BigEndian.Uint32(key[1:])
device := binary.BigEndian.Uint32(key[1+4:])
name := nulString(key[1+4+4:])
fmt.Printf("[device] F:%d D:%d N:%q", folder, device, name)
var f bep.FileInfo
err := proto.Unmarshal(it.Value(), &f)
if err != nil {
return err
}
fmt.Printf(" V:%v\n", &f)
case db.KeyTypeGlobal:
folder := binary.BigEndian.Uint32(key[1:])
name := nulString(key[1+4:])
var flv dbproto.VersionList
proto.Unmarshal(it.Value(), &flv)
fmt.Printf("[global] F:%d N:%q V:%s\n", folder, name, &flv)
case db.KeyTypeBlock:
folder := binary.BigEndian.Uint32(key[1:])
hash := key[1+4 : 1+4+32]
name := nulString(key[1+4+32:])
fmt.Printf("[block] F:%d H:%x N:%q I:%d\n", folder, hash, name, binary.BigEndian.Uint32(it.Value()))
case db.KeyTypeDeviceStatistic:
fmt.Printf("[dstat] K:%x V:%x\n", key, it.Value())
case db.KeyTypeFolderStatistic:
fmt.Printf("[fstat] K:%x V:%x\n", key, it.Value())
case db.KeyTypeVirtualMtime:
folder := binary.BigEndian.Uint32(key[1:])
name := nulString(key[1+4:])
val := it.Value()
var realTime, virtualTime time.Time
realTime.UnmarshalBinary(val[:len(val)/2])
virtualTime.UnmarshalBinary(val[len(val)/2:])
fmt.Printf("[mtime] F:%d N:%q R:%v V:%v\n", folder, name, realTime, virtualTime)
case db.KeyTypeFolderIdx:
key := binary.BigEndian.Uint32(key[1:])
fmt.Printf("[folderidx] K:%d V:%q\n", key, it.Value())
case db.KeyTypeDeviceIdx:
key := binary.BigEndian.Uint32(key[1:])
val := it.Value()
device := "<nil>"
if len(val) > 0 {
dev, err := protocol.DeviceIDFromBytes(val)
if err != nil {
device = fmt.Sprintf("<invalid %d bytes>", len(val))
} else {
device = dev.String()
}
}
fmt.Printf("[deviceidx] K:%d V:%s\n", key, device)
case db.KeyTypeIndexID:
device := binary.BigEndian.Uint32(key[1:])
folder := binary.BigEndian.Uint32(key[5:])
fmt.Printf("[indexid] D:%d F:%d I:%x\n", device, folder, it.Value())
case db.KeyTypeFolderMeta:
folder := binary.BigEndian.Uint32(key[1:])
fmt.Printf("[foldermeta] F:%d", folder)
var cs dbproto.CountsSet
if err := proto.Unmarshal(it.Value(), &cs); err != nil {
fmt.Printf(" (invalid)\n")
} else {
fmt.Printf(" V:%v\n", &cs)
}
case db.KeyTypeMiscData:
fmt.Printf("[miscdata] K:%q V:%q\n", key[1:], it.Value())
case db.KeyTypeSequence:
folder := binary.BigEndian.Uint32(key[1:])
seq := binary.BigEndian.Uint64(key[5:])
fmt.Printf("[sequence] F:%d S:%d V:%q\n", folder, seq, it.Value())
case db.KeyTypeNeed:
folder := binary.BigEndian.Uint32(key[1:])
file := string(key[5:])
fmt.Printf("[need] F:%d V:%q\n", folder, file)
case db.KeyTypeBlockList:
fmt.Printf("[blocklist] H:%x\n", key[1:])
case db.KeyTypeBlockListMap:
folder := binary.BigEndian.Uint32(key[1:])
hash := key[5:37]
fileName := string(key[37:])
fmt.Printf("[blocklistmap] F:%d H:%x N:%s\n", folder, hash, fileName)
case db.KeyTypeVersion:
fmt.Printf("[version] H:%x", key[1:])
var v bep.Vector
err := proto.Unmarshal(it.Value(), &v)
if err != nil {
fmt.Printf(" (invalid)\n")
} else {
fmt.Printf(" V:%v\n", &v)
}
case db.KeyTypePendingFolder:
device := binary.BigEndian.Uint32(key[1:])
folder := string(key[5:])
var of dbproto.ObservedFolder
proto.Unmarshal(it.Value(), &of)
fmt.Printf("[pendingFolder] D:%d F:%s V:%v\n", device, folder, &of)
case db.KeyTypePendingDevice:
device := "<invalid>"
dev, err := protocol.DeviceIDFromBytes(key[1:])
if err == nil {
device = dev.String()
}
var od dbproto.ObservedDevice
proto.Unmarshal(it.Value(), &od)
fmt.Printf("[pendingDevice] D:%v V:%v\n", device, &od)
default:
fmt.Printf("[??? %d]\n %x\n %x\n", key[0], key, it.Value())
}
}
return nil
}
+89
View File
@@ -0,0 +1,89 @@
// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package cli
import (
"cmp"
"encoding/binary"
"fmt"
"slices"
"github.com/syncthing/syncthing/lib/db"
)
func indexDumpSize() error {
type sizedElement struct {
key string
size int
}
ldb, err := getDB()
if err != nil {
return err
}
it, err := ldb.NewPrefixIterator(nil)
if err != nil {
return err
}
var elems []sizedElement
for it.Next() {
var ele sizedElement
key := it.Key()
switch key[0] {
case db.KeyTypeDevice:
folder := binary.BigEndian.Uint32(key[1:])
device := binary.BigEndian.Uint32(key[1+4:])
name := nulString(key[1+4+4:])
ele.key = fmt.Sprintf("DEVICE:%d:%d:%s", folder, device, name)
case db.KeyTypeGlobal:
folder := binary.BigEndian.Uint32(key[1:])
name := nulString(key[1+4:])
ele.key = fmt.Sprintf("GLOBAL:%d:%s", folder, name)
case db.KeyTypeBlock:
folder := binary.BigEndian.Uint32(key[1:])
hash := key[1+4 : 1+4+32]
name := nulString(key[1+4+32:])
ele.key = fmt.Sprintf("BLOCK:%d:%x:%s", folder, hash, name)
case db.KeyTypeDeviceStatistic:
ele.key = fmt.Sprintf("DEVICESTATS:%s", key[1:])
case db.KeyTypeFolderStatistic:
ele.key = fmt.Sprintf("FOLDERSTATS:%s", key[1:])
case db.KeyTypeVirtualMtime:
ele.key = fmt.Sprintf("MTIME:%s", key[1:])
case db.KeyTypeFolderIdx:
id := binary.BigEndian.Uint32(key[1:])
ele.key = fmt.Sprintf("FOLDERIDX:%d", id)
case db.KeyTypeDeviceIdx:
id := binary.BigEndian.Uint32(key[1:])
ele.key = fmt.Sprintf("DEVICEIDX:%d", id)
default:
ele.key = fmt.Sprintf("UNKNOWN:%x", key)
}
ele.size = len(it.Value())
elems = append(elems, ele)
}
slices.SortFunc(elems, func(a, b sizedElement) int {
return cmp.Compare(b.size, a.size)
})
for _, ele := range elems {
fmt.Println(ele.key, ele.size)
}
return nil
}
+435
View File
@@ -0,0 +1,435 @@
// Copyright (C) 2018 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package cli
import (
"bytes"
"cmp"
"encoding/binary"
"errors"
"fmt"
"slices"
"google.golang.org/protobuf/proto"
"github.com/syncthing/syncthing/internal/gen/bep"
"github.com/syncthing/syncthing/internal/gen/dbproto"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/protocol"
)
type fileInfoKey struct {
folder uint32
device uint32
name string
}
type globalKey struct {
folder uint32
name string
}
type sequenceKey struct {
folder uint32
sequence uint64
}
func indexCheck() (err error) {
ldb, err := getDB()
if err != nil {
return err
}
folders := make(map[uint32]string)
devices := make(map[uint32]string)
deviceToIDs := make(map[string]uint32)
fileInfos := make(map[fileInfoKey]*bep.FileInfo)
globals := make(map[globalKey]*dbproto.VersionList)
sequences := make(map[sequenceKey]string)
needs := make(map[globalKey]struct{})
blocklists := make(map[string]struct{})
versions := make(map[string]*bep.Vector)
usedBlocklists := make(map[string]struct{})
usedVersions := make(map[string]struct{})
var localDeviceKey uint32
success := true
defer func() {
if err == nil {
if success {
fmt.Println("Index check completed successfully.")
} else {
err = errors.New("Inconsistencies found in the index")
}
}
}()
it, err := ldb.NewPrefixIterator(nil)
if err != nil {
return err
}
for it.Next() {
key := it.Key()
switch key[0] {
case db.KeyTypeDevice:
folder := binary.BigEndian.Uint32(key[1:])
device := binary.BigEndian.Uint32(key[1+4:])
name := nulString(key[1+4+4:])
var f bep.FileInfo
err := proto.Unmarshal(it.Value(), &f)
if err != nil {
fmt.Println("Unable to unmarshal FileInfo:", err)
success = false
continue
}
fileInfos[fileInfoKey{folder, device, name}] = &f
case db.KeyTypeGlobal:
folder := binary.BigEndian.Uint32(key[1:])
name := nulString(key[1+4:])
var flv dbproto.VersionList
if err := proto.Unmarshal(it.Value(), &flv); err != nil {
fmt.Println("Unable to unmarshal VersionList:", err)
success = false
continue
}
globals[globalKey{folder, name}] = &flv
case db.KeyTypeFolderIdx:
key := binary.BigEndian.Uint32(it.Key()[1:])
folders[key] = string(it.Value())
case db.KeyTypeDeviceIdx:
key := binary.BigEndian.Uint32(it.Key()[1:])
devices[key] = string(it.Value())
deviceToIDs[string(it.Value())] = key
if bytes.Equal(it.Value(), protocol.LocalDeviceID[:]) {
localDeviceKey = key
}
case db.KeyTypeSequence:
folder := binary.BigEndian.Uint32(key[1:])
seq := binary.BigEndian.Uint64(key[5:])
val := it.Value()
sequences[sequenceKey{folder, seq}] = string(val[9:])
case db.KeyTypeNeed:
folder := binary.BigEndian.Uint32(key[1:])
name := nulString(key[1+4:])
needs[globalKey{folder, name}] = struct{}{}
case db.KeyTypeBlockList:
hash := string(key[1:])
blocklists[hash] = struct{}{}
case db.KeyTypeVersion:
hash := string(key[1:])
var v bep.Vector
if err := proto.Unmarshal(it.Value(), &v); err != nil {
fmt.Println("Unable to unmarshal Vector:", err)
success = false
continue
}
versions[hash] = &v
}
}
if localDeviceKey == 0 {
fmt.Println("Missing key for local device in device index (bailing out)")
success = false
return
}
var missingSeq []sequenceKey
for fk, fi := range fileInfos {
if fk.name != fi.Name {
fmt.Printf("Mismatching FileInfo name, %q (key) != %q (actual)\n", fk.name, fi.Name)
success = false
}
folder := folders[fk.folder]
if folder == "" {
fmt.Printf("Unknown folder ID %d for FileInfo %q\n", fk.folder, fk.name)
success = false
continue
}
if devices[fk.device] == "" {
fmt.Printf("Unknown device ID %d for FileInfo %q, folder %q\n", fk.folder, fk.name, folder)
success = false
}
if fk.device == localDeviceKey {
sk := sequenceKey{fk.folder, uint64(fi.Sequence)}
name, ok := sequences[sk]
if !ok {
fmt.Printf("Sequence entry missing for FileInfo %q, folder %q, seq %d\n", fi.Name, folder, fi.Sequence)
missingSeq = append(missingSeq, sk)
success = false
continue
}
if name != fi.Name {
fmt.Printf("Sequence entry refers to wrong name, %q (seq) != %q (FileInfo), folder %q, seq %d\n", name, fi.Name, folder, fi.Sequence)
success = false
}
}
if len(fi.Blocks) == 0 && len(fi.BlocksHash) != 0 {
key := string(fi.BlocksHash)
if _, ok := blocklists[key]; !ok {
fmt.Printf("Missing block list for file %q, block list hash %x\n", fi.Name, fi.BlocksHash)
success = false
} else {
usedBlocklists[key] = struct{}{}
}
}
if fi.VersionHash != nil {
key := string(fi.VersionHash)
if _, ok := versions[key]; !ok {
fmt.Printf("Missing version vector for file %q, version hash %x\n", fi.Name, fi.VersionHash)
success = false
} else {
usedVersions[key] = struct{}{}
}
}
_, ok := globals[globalKey{fk.folder, fk.name}]
if !ok {
fmt.Printf("Missing global for file %q\n", fi.Name)
success = false
continue
}
}
// Aggregate the ranges of missing sequence entries, print them
slices.SortFunc(missingSeq, func(a, b sequenceKey) int {
if a.folder != b.folder {
return cmp.Compare(a.folder, b.folder)
}
return cmp.Compare(a.sequence, b.sequence)
})
var folder uint32
var startSeq, prevSeq uint64
for _, sk := range missingSeq {
if folder != sk.folder || sk.sequence != prevSeq+1 {
if folder != 0 {
fmt.Printf("Folder %d missing %d sequence entries: #%d - #%d\n", folder, prevSeq-startSeq+1, startSeq, prevSeq)
}
startSeq = sk.sequence
folder = sk.folder
}
prevSeq = sk.sequence
}
if folder != 0 {
fmt.Printf("Folder %d missing %d sequence entries: #%d - #%d\n", folder, prevSeq-startSeq+1, startSeq, prevSeq)
}
for gk, vl := range globals {
folder := folders[gk.folder]
if folder == "" {
fmt.Printf("Unknown folder ID %d for VersionList %q\n", gk.folder, gk.name)
success = false
}
checkGlobal := func(i int, device []byte, version protocol.Vector, invalid, deleted bool) {
dev, ok := deviceToIDs[string(device)]
if !ok {
fmt.Printf("VersionList %q, folder %q refers to unknown device %q\n", gk.name, folder, device)
success = false
}
fi, ok := fileInfos[fileInfoKey{gk.folder, dev, gk.name}]
if !ok {
fmt.Printf("VersionList %q, folder %q, entry %d refers to unknown FileInfo\n", gk.name, folder, i)
success = false
}
fiv := fi.Version
if fi.VersionHash != nil {
fiv = versions[string(fi.VersionHash)]
}
if !protocol.VectorFromWire(fiv).Equal(version) {
fmt.Printf("VersionList %q, folder %q, entry %d, FileInfo version mismatch, %v (VersionList) != %v (FileInfo)\n", gk.name, folder, i, version, fi.Version)
success = false
}
ffi := protocol.FileInfoFromDB(fi)
if ffi.IsInvalid() != invalid {
fmt.Printf("VersionList %q, folder %q, entry %d, FileInfo invalid mismatch, %v (VersionList) != %v (FileInfo)\n", gk.name, folder, i, invalid, ffi.IsInvalid())
success = false
}
if ffi.IsDeleted() != deleted {
fmt.Printf("VersionList %q, folder %q, entry %d, FileInfo deleted mismatch, %v (VersionList) != %v (FileInfo)\n", gk.name, folder, i, deleted, ffi.IsDeleted())
success = false
}
}
for i, fv := range vl.Versions {
ver := protocol.VectorFromWire(fv.Version)
for _, device := range fv.Devices {
checkGlobal(i, device, ver, false, fv.Deleted)
}
for _, device := range fv.InvalidDevices {
checkGlobal(i, device, ver, true, fv.Deleted)
}
}
// If we need this file we should have a need entry for it. False
// positives from needsLocally for deleted files, where we might
// legitimately lack an entry if we never had it, and ignored files.
if needsLocally(vl) {
_, ok := needs[gk]
if !ok {
fv, _ := vlGetGlobal(vl)
devB, _ := fvFirstDevice(fv)
dev := deviceToIDs[string(devB)]
fi := protocol.FileInfoFromDB(fileInfos[fileInfoKey{gk.folder, dev, gk.name}])
if !fi.IsDeleted() && !fi.IsIgnored() {
fmt.Printf("Missing need entry for needed file %q, folder %q\n", gk.name, folder)
}
}
}
}
seenSeq := make(map[fileInfoKey]uint64)
for sk, name := range sequences {
folder := folders[sk.folder]
if folder == "" {
fmt.Printf("Unknown folder ID %d for sequence entry %d, %q\n", sk.folder, sk.sequence, name)
success = false
continue
}
if prev, ok := seenSeq[fileInfoKey{folder: sk.folder, name: name}]; ok {
fmt.Printf("Duplicate sequence entry for %q, folder %q, seq %d (prev %d)\n", name, folder, sk.sequence, prev)
success = false
}
seenSeq[fileInfoKey{folder: sk.folder, name: name}] = sk.sequence
fi, ok := fileInfos[fileInfoKey{sk.folder, localDeviceKey, name}]
if !ok {
fmt.Printf("Missing FileInfo for sequence entry %d, folder %q, %q\n", sk.sequence, folder, name)
success = false
continue
}
if fi.Sequence != int64(sk.sequence) {
fmt.Printf("Sequence mismatch for %q, folder %q, %d (key) != %d (FileInfo)\n", name, folder, sk.sequence, fi.Sequence)
success = false
}
}
for nk := range needs {
folder := folders[nk.folder]
if folder == "" {
fmt.Printf("Unknown folder ID %d for need entry %q\n", nk.folder, nk.name)
success = false
continue
}
vl, ok := globals[nk]
if !ok {
fmt.Printf("Missing global for need entry %q, folder %q\n", nk.name, folder)
success = false
continue
}
if !needsLocally(vl) {
fmt.Printf("Need entry for file we don't need, %q, folder %q\n", nk.name, folder)
success = false
}
}
if d := len(blocklists) - len(usedBlocklists); d > 0 {
fmt.Printf("%d block list entries out of %d needs GC\n", d, len(blocklists))
}
if d := len(versions) - len(usedVersions); d > 0 {
fmt.Printf("%d version entries out of %d needs GC\n", d, len(versions))
}
return nil
}
func needsLocally(vl *dbproto.VersionList) bool {
gfv, gok := vlGetGlobal(vl)
if !gok { // That's weird, but we hardly need something non-existent
return false
}
fv, ok := vlGet(vl, protocol.LocalDeviceID[:])
return db.Need(gfv, ok, protocol.VectorFromWire(fv.Version))
}
// Get returns a FileVersion that contains the given device and whether it has
// been found at all.
func vlGet(vl *dbproto.VersionList, device []byte) (*dbproto.FileVersion, bool) {
_, i, _, ok := vlFindDevice(vl, device)
if !ok {
return &dbproto.FileVersion{}, false
}
return vl.Versions[i], true
}
// GetGlobal returns the current global FileVersion. The returned FileVersion
// may be invalid, if all FileVersions are invalid. Returns false only if
// VersionList is empty.
func vlGetGlobal(vl *dbproto.VersionList) (*dbproto.FileVersion, bool) {
i := vlFindGlobal(vl)
if i == -1 {
return nil, false
}
return vl.Versions[i], true
}
// findGlobal returns the first version that isn't invalid, or if all versions are
// invalid just the first version (i.e. 0) or -1, if there's no versions at all.
func vlFindGlobal(vl *dbproto.VersionList) int {
for i := range vl.Versions {
if !fvIsInvalid(vl.Versions[i]) {
return i
}
}
if len(vl.Versions) == 0 {
return -1
}
return 0
}
// findDevice returns whether the device is in InvalidVersions or Versions and
// in InvalidDevices or Devices (true for invalid), the positions in the version
// and device slices and whether it has been found at all.
func vlFindDevice(vl *dbproto.VersionList, device []byte) (bool, int, int, bool) {
for i, v := range vl.Versions {
if j := deviceIndex(v.Devices, device); j != -1 {
return false, i, j, true
}
if j := deviceIndex(v.InvalidDevices, device); j != -1 {
return true, i, j, true
}
}
return false, -1, -1, false
}
func deviceIndex(devices [][]byte, device []byte) int {
for i, dev := range devices {
if bytes.Equal(device, dev) {
return i
}
}
return -1
}
func fvFirstDevice(fv *dbproto.FileVersion) ([]byte, bool) {
if len(fv.Devices) != 0 {
return fv.Devices[0], true
}
if len(fv.InvalidDevices) != 0 {
return fv.InvalidDevices[0], true
}
return nil, false
}
func fvIsInvalid(fv *dbproto.FileVersion) bool {
return fv == nil || len(fv.Devices) == 0
}
+10 -2
View File
@@ -14,12 +14,15 @@ import (
"github.com/alecthomas/kong" "github.com/alecthomas/kong"
"github.com/kballard/go-shellquote" "github.com/kballard/go-shellquote"
"github.com/syncthing/syncthing/cmd/syncthing/cmdutil"
"github.com/syncthing/syncthing/lib/config" "github.com/syncthing/syncthing/lib/config"
) )
type CLI struct { type CLI struct {
GUIAddress string `name:"gui-address" env:"STGUIADDRESS"` cmdutil.CommonOptions
GUIAPIKey string `name:"gui-apikey" env:"STGUIAPIKEY"` DataDir string `name:"data" placeholder:"PATH" env:"STDATADIR" help:"Set data directory (database and logs)"`
GUIAddress string `name:"gui-address"`
GUIAPIKey string `name:"gui-apikey"`
Show showCommand `cmd:"" help:"Show command group"` Show showCommand `cmd:"" help:"Show command group"`
Debug debugCommand `cmd:"" help:"Debug command group"` Debug debugCommand `cmd:"" help:"Debug command group"`
@@ -34,6 +37,11 @@ type Context struct {
} }
func (cli CLI) AfterApply(kongCtx *kong.Context) error { func (cli CLI) AfterApply(kongCtx *kong.Context) error {
err := cmdutil.SetConfigDataLocationsFromFlags(cli.HomeDir, cli.ConfDir, cli.DataDir)
if err != nil {
return fmt.Errorf("command line options: %w", err)
}
clientFactory := &apiClientFactory{ clientFactory := &apiClientFactory{
cfg: config.GUIConfiguration{ cfg: config.GUIConfiguration{
RawAddress: cli.GUIAddress, RawAddress: cli.GUIAddress,
+15
View File
@@ -17,6 +17,8 @@ import (
"path/filepath" "path/filepath"
"github.com/syncthing/syncthing/lib/config" "github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/db/backend"
"github.com/syncthing/syncthing/lib/locations"
) )
func responseToBArray(response *http.Response) ([]byte, error) { func responseToBArray(response *http.Response) ([]byte, error) {
@@ -131,6 +133,19 @@ func prettyPrintResponse(response *http.Response) error {
return prettyPrintJSON(data) return prettyPrintJSON(data)
} }
func getDB() (backend.Backend, error) {
return backend.OpenLevelDBRO(locations.Get(locations.Database))
}
func nulString(bs []byte) string {
for i := range bs {
if bs[i] == 0 {
return string(bs[:i])
}
}
return string(bs)
}
func normalizePath(path string) string { func normalizePath(path string) string {
return filepath.ToSlash(filepath.Clean(path)) return filepath.ToSlash(filepath.Clean(path))
} }
+16
View File
@@ -0,0 +1,16 @@
// Copyright (C) 2021 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package cmdutil
// CommonOptions are reused among several subcommands
type CommonOptions struct {
buildCommonOptions
ConfDir string `name:"config" placeholder:"PATH" env:"STCONFDIR" help:"Set configuration directory (config and keys)"`
HomeDir string `name:"home" placeholder:"PATH" env:"STHOMEDIR" help:"Set configuration and data directory"`
NoDefaultFolder bool `env:"STNODEFAULTFOLDER" help:"Don't create the \"default\" folder on first startup"`
SkipPortProbing bool `help:"Don't try to find free ports for GUI and listen addresses on first startup"`
}
@@ -7,8 +7,8 @@
//go:build !windows //go:build !windows
// +build !windows // +build !windows
package main package cmdutil
type buildSpecificOptions struct { type buildCommonOptions struct {
HideConsole bool `hidden:""` HideConsole bool `hidden:""`
} }
@@ -4,8 +4,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this file, // License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/. // You can obtain one at https://mozilla.org/MPL/2.0/.
package main package cmdutil
type buildSpecificOptions struct { type buildCommonOptions struct {
HideConsole bool `name:"no-console" help:"Hide console window" env:"STHIDECONSOLE"` HideConsole bool `name:"no-console" help:"Hide console window"`
} }
+35
View File
@@ -0,0 +1,35 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package cmdutil
import (
"errors"
"github.com/syncthing/syncthing/lib/locations"
)
func SetConfigDataLocationsFromFlags(homeDir, confDir, dataDir string) error {
homeSet := homeDir != ""
confSet := confDir != ""
dataSet := dataDir != ""
switch {
case dataSet != confSet:
return errors.New("either both or none of --config and --data must be given, use --home to set both at once")
case homeSet && dataSet:
return errors.New("--home must not be used together with --config and --data")
case homeSet:
confDir = homeDir
dataDir = homeDir
fallthrough
case dataSet:
if err := locations.SetBaseDir(locations.ConfigBaseDir, confDir); err != nil {
return err
}
return locations.SetBaseDir(locations.DataBaseDir, dataDir)
}
return nil
}
+3 -6
View File
@@ -11,15 +11,12 @@ import (
"context" "context"
"crypto/sha256" "crypto/sha256"
"fmt" "fmt"
"log/slog"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"slices" "slices"
"strings" "strings"
"time" "time"
"github.com/syncthing/syncthing/internal/slogutil"
) )
const ( const (
@@ -36,7 +33,7 @@ const (
func uploadPanicLogs(ctx context.Context, urlBase, dir string) { func uploadPanicLogs(ctx context.Context, urlBase, dir string) {
files, err := filepath.Glob(filepath.Join(dir, "panic-*.log")) files, err := filepath.Glob(filepath.Join(dir, "panic-*.log"))
if err != nil { if err != nil {
slog.ErrorContext(ctx, "Failed to list panic logs", slogutil.Error(err)) l.Warnln("Failed to list panic logs:", err)
return return
} }
@@ -51,7 +48,7 @@ func uploadPanicLogs(ctx context.Context, urlBase, dir string) {
} }
if err := uploadPanicLog(ctx, urlBase, file); err != nil { if err := uploadPanicLog(ctx, urlBase, file); err != nil {
slog.ErrorContext(ctx, "Reporting crash", slogutil.Error(err)) l.Warnln("Reporting crash:", err)
} else { } else {
// Rename the log so we don't have to try to report it again. This // Rename the log so we don't have to try to report it again. This
// succeeds, or it does not. There is no point complaining about it. // succeeds, or it does not. There is no point complaining about it.
@@ -74,7 +71,7 @@ func uploadPanicLog(ctx context.Context, urlBase, file string) error {
data = filterLogLines(data) data = filterLogLines(data)
hash := fmt.Sprintf("%x", sha256.Sum256(data)) hash := fmt.Sprintf("%x", sha256.Sum256(data))
slog.InfoContext(ctx, "Reporting crash", slogutil.FilePath(filepath.Base(file)), slog.String("id", hash[:8])) l.Infof("Reporting crash found in %s (report ID %s) ...\n", filepath.Base(file), hash[:8])
url := fmt.Sprintf("%s/%s", urlBase, hash) url := fmt.Sprintf("%s/%s", urlBase, hash)
headReq, err := http.NewRequest(http.MethodHead, url, nil) headReq, err := http.NewRequest(http.MethodHead, url, nil)
+4 -2
View File
@@ -6,6 +6,8 @@
package main package main
import "github.com/syncthing/syncthing/internal/slogutil" import (
"github.com/syncthing/syncthing/lib/logger"
)
func init() { slogutil.RegisterPackage("Main package") } var l = logger.DefaultLogger.NewFacility("main", "Main package")
+1 -1
View File
@@ -238,7 +238,7 @@ func (c *CLI) decryptFile(encFi *protocol.FileInfo, plainFi *protocol.FileInfo,
} }
// Verify the hash against the plaintext block info // Verify the hash against the plaintext block info
if !scanner.Validate(dec, plainBlock.Hash) { if !scanner.Validate(dec, plainBlock.Hash, 0) {
// The block decrypted correctly but fails the hash check. This // The block decrypted correctly but fails the hash check. This
// is odd and unexpected, but it it's still a valid block from // is odd and unexpected, but it it's still a valid block from
// the source. The file might have changed while we pulled it? // the source. The file might have changed while we pulled it?
+29 -13
View File
@@ -11,25 +11,42 @@ import (
"bufio" "bufio"
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"log/slog"
"os" "os"
"github.com/syncthing/syncthing/cmd/syncthing/cmdutil"
"github.com/syncthing/syncthing/lib/config" "github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/events" "github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/fs" "github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/locations" "github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/logger"
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/syncthing" "github.com/syncthing/syncthing/lib/syncthing"
) )
type CLI struct { type CLI struct {
cmdutil.CommonOptions
GUIUser string `placeholder:"STRING" help:"Specify new GUI authentication user name"` GUIUser string `placeholder:"STRING" help:"Specify new GUI authentication user name"`
GUIPassword string `placeholder:"STRING" help:"Specify new GUI authentication password (use - to read from standard input)"` GUIPassword string `placeholder:"STRING" help:"Specify new GUI authentication password (use - to read from standard input)"`
NoPortProbing bool `help:"Don't try to find free ports for GUI and listen addresses on first startup" env:"STNOPORTPROBING"`
} }
func (c *CLI) Run() error { func (c *CLI) Run(l logger.Logger) error {
if c.HideConsole {
osutil.HideConsole()
}
if c.HomeDir != "" {
if c.ConfDir != "" {
return errors.New("--home must not be used together with --config")
}
c.ConfDir = c.HomeDir
}
if c.ConfDir == "" {
c.ConfDir = locations.GetBaseDir(locations.ConfigBaseDir)
}
// Support reading the password from a pipe or similar // Support reading the password from a pipe or similar
if c.GUIPassword == "-" { if c.GUIPassword == "-" {
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
@@ -40,13 +57,13 @@ func (c *CLI) Run() error {
c.GUIPassword = string(password) c.GUIPassword = string(password)
} }
if err := Generate(locations.GetBaseDir(locations.ConfigBaseDir), c.GUIUser, c.GUIPassword, c.NoPortProbing); err != nil { if err := Generate(l, c.ConfDir, c.GUIUser, c.GUIPassword, c.NoDefaultFolder, c.SkipPortProbing); err != nil {
return fmt.Errorf("failed to generate config and keys: %w", err) return fmt.Errorf("failed to generate config and keys: %w", err)
} }
return nil return nil
} }
func Generate(confDir, guiUser, guiPassword string, skipPortProbing bool) error { func Generate(l logger.Logger, confDir, guiUser, guiPassword string, noDefaultFolder, skipPortProbing bool) error {
dir, err := fs.ExpandTilde(confDir) dir, err := fs.ExpandTilde(confDir)
if err != nil { if err != nil {
return err return err
@@ -61,21 +78,20 @@ func Generate(confDir, guiUser, guiPassword string, skipPortProbing bool) error
certFile, keyFile := locations.Get(locations.CertFile), locations.Get(locations.KeyFile) certFile, keyFile := locations.Get(locations.CertFile), locations.Get(locations.KeyFile)
cert, err := tls.LoadX509KeyPair(certFile, keyFile) cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err == nil { if err == nil {
slog.Warn("Key exists; will not overwrite") l.Warnln("Key exists; will not overwrite.")
} else { } else {
cert, err = syncthing.GenerateCertificate(certFile, keyFile) cert, err = syncthing.GenerateCertificate(certFile, keyFile)
if err != nil { if err != nil {
return fmt.Errorf("create certificate: %w", err) return fmt.Errorf("create certificate: %w", err)
} }
} }
myID = protocol.NewDeviceID(cert.Certificate[0]) myID = protocol.NewDeviceID(cert.Certificate[0])
slog.Info("Calculated device ID", slog.String("device", myID.String())) l.Infoln("Device ID:", myID)
cfgFile := locations.Get(locations.ConfigFile) cfgFile := locations.Get(locations.ConfigFile)
cfg, _, err := config.Load(cfgFile, myID, events.NoopLogger) cfg, _, err := config.Load(cfgFile, myID, events.NoopLogger)
if fs.IsNotExist(err) { if fs.IsNotExist(err) {
if cfg, err = syncthing.DefaultConfig(cfgFile, myID, events.NoopLogger, skipPortProbing); err != nil { if cfg, err = syncthing.DefaultConfig(cfgFile, myID, events.NoopLogger, noDefaultFolder, skipPortProbing); err != nil {
return fmt.Errorf("create config: %w", err) return fmt.Errorf("create config: %w", err)
} }
} else if err != nil { } else if err != nil {
@@ -88,7 +104,7 @@ func Generate(confDir, guiUser, guiPassword string, skipPortProbing bool) error
var updateErr error var updateErr error
waiter, err := cfg.Modify(func(cfg *config.Configuration) { waiter, err := cfg.Modify(func(cfg *config.Configuration) {
updateErr = updateGUIAuthentication(&cfg.GUI, guiUser, guiPassword) updateErr = updateGUIAuthentication(l, &cfg.GUI, guiUser, guiPassword)
}) })
if err != nil { if err != nil {
return fmt.Errorf("modify config: %w", err) return fmt.Errorf("modify config: %w", err)
@@ -104,17 +120,17 @@ func Generate(confDir, guiUser, guiPassword string, skipPortProbing bool) error
return nil return nil
} }
func updateGUIAuthentication(guiCfg *config.GUIConfiguration, guiUser, guiPassword string) error { func updateGUIAuthentication(l logger.Logger, guiCfg *config.GUIConfiguration, guiUser, guiPassword string) error {
if guiUser != "" && guiCfg.User != guiUser { if guiUser != "" && guiCfg.User != guiUser {
guiCfg.User = guiUser guiCfg.User = guiUser
slog.Info("Updated GUI authentication user", "name", guiUser) l.Infoln("Updated GUI authentication user name:", guiUser)
} }
if guiPassword != "" && guiCfg.Password != guiPassword { if guiPassword != "" && guiCfg.Password != guiPassword {
if err := guiCfg.SetPassword(guiPassword); err != nil { if err := guiCfg.SetPassword(guiPassword); err != nil {
return fmt.Errorf("failed to set GUI authentication password: %w", err) return fmt.Errorf("failed to set GUI authentication password: %w", err)
} }
slog.Info("Updated GUI authentication password") l.Infoln("Updated GUI authentication password.")
} }
return nil return nil
} }
+2 -5
View File
@@ -8,21 +8,18 @@ package main
import ( import (
"fmt" "fmt"
"log/slog"
"os" "os"
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"syscall" "syscall"
"time" "time"
"github.com/syncthing/syncthing/internal/slogutil"
) )
func startHeapProfiler() { func startHeapProfiler() {
slog.Debug("Starting heap profiling") l.Debugln("Starting heap profiling")
go func() { go func() {
err := saveHeapProfiles(1) // Only returns on error err := saveHeapProfiles(1) // Only returns on error
slog.Error("Heap profiler failed", slogutil.Error(err)) l.Warnln("Heap profiler failed:", err)
panic("Heap profiler failed") panic("Heap profiler failed")
}() }()
} }
+314 -408
View File
File diff suppressed because it is too large Load Diff
+44 -27
View File
@@ -11,28 +11,26 @@ import (
"context" "context"
"fmt" "fmt"
"io" "io"
"log/slog"
"os" "os"
"os/exec" "os/exec"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"
"syscall" "syscall"
"time" "time"
"github.com/syncthing/syncthing/internal/slogutil"
"github.com/syncthing/syncthing/lib/build" "github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/fs" "github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/locations" "github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/svcutil" "github.com/syncthing/syncthing/lib/svcutil"
"github.com/syncthing/syncthing/lib/sync"
) )
var ( var (
stdoutFirstLines []string // The first 10 lines of stdout stdoutFirstLines []string // The first 10 lines of stdout
stdoutLastLines []string // The last 50 lines of stdout stdoutLastLines []string // The last 50 lines of stdout
stdoutMut sync.Mutex stdoutMut = sync.NewMutex()
) )
const ( const (
@@ -45,7 +43,9 @@ const (
panicUploadNoticeWait = 10 * time.Second panicUploadNoticeWait = 10 * time.Second
) )
func (c *serveCmd) monitorMain() { func monitorMain(options serveOptions) {
l.SetPrefix("[monitor] ")
var dst io.Writer = os.Stdout var dst io.Writer = os.Stdout
logFile := locations.Get(locations.LogFile) logFile := locations.Get(locations.LogFile)
@@ -58,13 +58,13 @@ func (c *serveCmd) monitorMain() {
open := func(name string) (io.WriteCloser, error) { open := func(name string) (io.WriteCloser, error) {
return newAutoclosedFile(name, logFileAutoCloseDelay, logFileMaxOpenTime) return newAutoclosedFile(name, logFileAutoCloseDelay, logFileMaxOpenTime)
} }
if c.LogMaxSize > 0 { if options.LogMaxSize > 0 {
fileDst, err = newRotatedFile(logFile, open, int64(c.LogMaxSize), c.LogMaxFiles) fileDst, err = newRotatedFile(logFile, open, int64(options.LogMaxSize), options.LogMaxFiles)
} else { } else {
fileDst, err = open(logFile) fileDst, err = open(logFile)
} }
if err != nil { if err != nil {
slog.Error("Failed to set up logging to file, proceeding with logging to stdout only", slogutil.Error(err)) l.Warnln("Failed to set up logging to file, proceeding with logging to stdout only:", err)
} else { } else {
if build.IsWindows { if build.IsWindows {
// Translate line breaks to Windows standard // Translate line breaks to Windows standard
@@ -78,14 +78,14 @@ func (c *serveCmd) monitorMain() {
// Log to both stdout and file. // Log to both stdout and file.
dst = io.MultiWriter(dst, fileDst) dst = io.MultiWriter(dst, fileDst)
slog.Info("Saved log output", slogutil.FilePath(logFile)) l.Infof(`Log output saved to file "%s"`, logFile)
} }
} }
args := os.Args args := os.Args
binary, err := getBinary(args[0]) binary, err := getBinary(args[0])
if err != nil { if err != nil {
slog.Error("Failed to start the main Syncthing process", slogutil.Error(err)) l.Warnln("Error starting the main Syncthing process:", err)
panic("Error starting the main Syncthing process") panic("Error starting the main Syncthing process")
} }
var restarts [restartCounts]time.Time var restarts [restartCounts]time.Time
@@ -102,7 +102,7 @@ func (c *serveCmd) monitorMain() {
maybeReportPanics() maybeReportPanics()
if t := time.Since(restarts[0]); t < restartLoopThreshold { if t := time.Since(restarts[0]); t < restartLoopThreshold {
slog.Error("Too many restarts; not retrying further", slog.Int("count", restartCounts), slog.Any("interval", t)) l.Warnf("%d restarts in %v; not retrying further", restartCounts, t)
os.Exit(svcutil.ExitError.AsInt()) os.Exit(svcutil.ExitError.AsInt())
} }
@@ -122,10 +122,10 @@ func (c *serveCmd) monitorMain() {
panic(err) panic(err)
} }
slog.Debug("Starting syncthing") l.Debugln("Starting syncthing")
err = cmd.Start() err = cmd.Start()
if err != nil { if err != nil {
slog.Error("Failed to start the main Syncthing process", slogutil.Error(err)) l.Warnln("Error starting the main Syncthing process:", err)
panic("Error starting the main Syncthing process") panic("Error starting the main Syncthing process")
} }
@@ -134,7 +134,7 @@ func (c *serveCmd) monitorMain() {
stdoutLastLines = make([]string, 0, 50) stdoutLastLines = make([]string, 0, 50)
stdoutMut.Unlock() stdoutMut.Unlock()
var wg sync.WaitGroup wg := sync.NewWaitGroup()
wg.Add(1) wg.Add(1)
go func() { go func() {
@@ -158,13 +158,13 @@ func (c *serveCmd) monitorMain() {
stopped := false stopped := false
select { select {
case s := <-stopSign: case s := <-stopSign:
slog.Info("Received signal; exiting", "signal", s) l.Infof("Signal %d received; exiting", s)
cmd.Process.Signal(sigTerm) cmd.Process.Signal(sigTerm)
err = <-exit err = <-exit
stopped = true stopped = true
case s := <-restartSign: case s := <-restartSign:
slog.Info("Received signal; restarting", "signal", s) l.Infof("Signal %d received; restarting", s)
cmd.Process.Signal(sigHup) cmd.Process.Signal(sigHup)
err = <-exit err = <-exit
@@ -178,25 +178,25 @@ func (c *serveCmd) monitorMain() {
if exiterr, ok := err.(*exec.ExitError); ok { if exiterr, ok := err.(*exec.ExitError); ok {
exitCode := exiterr.ExitCode() exitCode := exiterr.ExitCode()
if stopped || c.NoRestart { if stopped || options.NoRestart {
os.Exit(exitCode) os.Exit(exitCode)
} }
if exitCode == svcutil.ExitUpgrade.AsInt() { if exitCode == svcutil.ExitUpgrade.AsInt() {
// Restart the monitor process to release the .old // Restart the monitor process to release the .old
// binary as part of the upgrade process. // binary as part of the upgrade process.
slog.Info("Restarting monitor...") l.Infoln("Restarting monitor...")
if err = restartMonitor(binary, args); err != nil { if err = restartMonitor(binary, args); err != nil {
slog.Error("Failed to restart monitor", slogutil.Error(err)) l.Warnln("Restart:", err)
} }
os.Exit(exitCode) os.Exit(exitCode)
} }
} }
if c.NoRestart { if options.NoRestart {
os.Exit(svcutil.ExitError.AsInt()) os.Exit(svcutil.ExitError.AsInt())
} }
slog.Info("Syncthing exited", slogutil.Error(err)) l.Infoln("Syncthing exited:", err)
time.Sleep(restartPause) time.Sleep(restartPause)
if first { if first {
@@ -243,13 +243,29 @@ func copyStderr(stderr io.Reader, dst io.Writer) {
if panicFd == nil && (strings.HasPrefix(line, "panic:") || strings.HasPrefix(line, "fatal error:")) { if panicFd == nil && (strings.HasPrefix(line, "panic:") || strings.HasPrefix(line, "fatal error:")) {
panicFd, err = os.Create(locations.GetTimestamped(locations.PanicLog)) panicFd, err = os.Create(locations.GetTimestamped(locations.PanicLog))
if err != nil { if err != nil {
slog.Error("Failed to create panic log", slogutil.Error(err)) l.Warnln("Create panic log:", err)
continue continue
} }
slog.Error("Panic detected, writing to file", slogutil.FilePath(panicFd.Name())) l.Warnf("Panic detected, writing to \"%s\"", panicFd.Name())
slog.Info("Please check for existing issues with similar panic message at https://github.com/syncthing/syncthing/issues/") if strings.Contains(line, "leveldb") && strings.Contains(line, "corrupt") {
slog.Info("If no issue with similar panic message exists, please create a new issue with the panic log attached") l.Warnln(`
*********************************************************************************
* Crash due to corrupt database. *
* *
* This crash usually occurs due to one of the following reasons: *
* - Syncthing being stopped abruptly (killed/loss of power) *
* - Bad hardware (memory/disk issues) *
* - Software that affects disk writes (SSD caching software and similar) *
* *
* Please see the following URL for instructions on how to recover: *
* https://docs.syncthing.net/users/faq.html#my-syncthing-database-is-corrupt *
*********************************************************************************
`)
} else {
l.Warnln("Please check for existing issues with similar panic message at https://github.com/syncthing/syncthing/issues/")
l.Warnln("If no issue with similar panic message exists, please create a new issue with the panic log attached")
}
stdoutMut.Lock() stdoutMut.Lock()
for _, line := range stdoutFirstLines { for _, line := range stdoutFirstLines {
@@ -430,6 +446,7 @@ func newAutoclosedFile(name string, closeDelay, maxOpenTime time.Duration) (*aut
name: name, name: name,
closeDelay: closeDelay, closeDelay: closeDelay,
maxOpenTime: maxOpenTime, maxOpenTime: maxOpenTime,
mut: sync.NewMutex(),
closed: make(chan struct{}), closed: make(chan struct{}),
closeTimer: time.NewTimer(time.Minute), closeTimer: time.NewTimer(time.Minute),
} }
@@ -537,7 +554,7 @@ func maybeReportPanics() {
// Try to get a config to see if/where panics should be reported. // Try to get a config to see if/where panics should be reported.
cfg, err := loadOrDefaultConfig() cfg, err := loadOrDefaultConfig()
if err != nil { if err != nil {
slog.Error("Couldn't load config; not reporting crash") l.Warnln("Couldn't load config; not reporting crash")
return return
} }
@@ -557,7 +574,7 @@ func maybeReportPanics() {
case <-ctx.Done(): case <-ctx.Done():
return return
case <-time.After(panicUploadNoticeWait): case <-time.After(panicUploadNoticeWait):
slog.Warn("Uploading crash reports is taking a while, please wait") l.Warnln("Uploading crash reports is taking a while, please wait...")
} }
}() }()
+26 -59
View File
@@ -16,9 +16,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/protocol"
"golang.org/x/exp/constraints"
) )
func startPerfStats() { func startPerfStats() {
@@ -31,68 +29,37 @@ func savePerfStats(file string) {
panic(err) panic(err)
} }
var prevTime time.Time var prevUsage int64
var curRus, prevRus syscall.Rusage var prevTime int64
var curMem, prevMem runtime.MemStats var rusage syscall.Rusage
var memstats runtime.MemStats
var prevIn, prevOut int64 var prevIn, prevOut int64
t0 := time.Now() t0 := time.Now()
syscall.Getrusage(syscall.RUSAGE_SELF, &prevRus)
runtime.ReadMemStats(&prevMem)
fmt.Fprintf(fd, "TIME_S\tCPU_S\tHEAP_KIB\tRSS_KIB\tNETIN_KBPS\tNETOUT_KBPS\tDBSIZE_KIB\n")
for t := range time.NewTicker(250 * time.Millisecond).C { for t := range time.NewTicker(250 * time.Millisecond).C {
syscall.Getrusage(syscall.RUSAGE_SELF, &curRus) if err := syscall.Getrusage(syscall.RUSAGE_SELF, &rusage); err != nil {
runtime.ReadMemStats(&curMem)
in, out := protocol.TotalInOut()
timeDiff := t.Sub(prevTime)
fmt.Fprintf(fd, "%.03f\t%f\t%d\t%d\t%.0f\t%.0f\t%d\n",
t.Sub(t0).Seconds(),
rate(cpusec(&prevRus), cpusec(&curRus), timeDiff, 1),
(curMem.Sys-curMem.HeapReleased)/1024,
curRus.Maxrss/1024,
rate(prevIn, in, timeDiff, 1e3),
rate(prevOut, out, timeDiff, 1e3),
dirsize(locations.Get(locations.Database))/1024,
)
prevTime = t
prevRus = curRus
prevMem = curMem
prevIn, prevOut = in, out
}
}
func cpusec(r *syscall.Rusage) float64 {
return float64(r.Utime.Nano()+r.Stime.Nano()) / float64(time.Second)
}
type number interface {
constraints.Float | constraints.Integer
}
func rate[T number](prev, cur T, d time.Duration, div float64) float64 {
diff := cur - prev
rate := float64(diff) / d.Seconds() / div
return rate
}
func dirsize(location string) int64 {
entries, err := os.ReadDir(location)
if err != nil {
return 0
}
var size int64
for _, entry := range entries {
fi, err := entry.Info()
if err != nil {
continue continue
} }
size += fi.Size()
}
return size curTime := time.Now().UnixNano()
timeDiff := curTime - prevTime
curUsage := rusage.Utime.Nano() + rusage.Stime.Nano()
usageDiff := curUsage - prevUsage
cpuUsagePercent := 100 * float64(usageDiff) / float64(timeDiff)
prevTime = curTime
prevUsage = curUsage
in, out := protocol.TotalInOut()
var inRate, outRate float64
if timeDiff > 0 {
inRate = float64(in-prevIn) / (float64(timeDiff) / 1e9) // bytes per second
outRate = float64(out-prevOut) / (float64(timeDiff) / 1e9) // bytes per second
}
prevIn, prevOut = in, out
runtime.ReadMemStats(&memstats)
startms := int(t.Sub(t0).Seconds() * 1000)
fmt.Fprintf(fd, "%d\t%f\t%d\t%d\t%.0f\t%.0f\n", startms, cpuUsagePercent, memstats.Alloc, memstats.Sys-memstats.HeapReleased, inRate, outRate)
}
} }
-7
View File
@@ -32,10 +32,3 @@
darwin: "20" darwin: "20"
linux: "3.2" linux: "3.2"
windows: "10.0" windows: "10.0"
- runtime: go1.25
requirements:
# macOS 12 (Monterey) per https://tip.golang.org/doc/go1.25#darwin
darwin: "21"
linux: "3.2"
windows: "10.0"
+1 -1
View File
@@ -2,7 +2,7 @@
Name=Syncthing Web UI Name=Syncthing Web UI
GenericName=File synchronization UI GenericName=File synchronization UI
Comment=Opens Syncthing's Web UI in the default browser (Syncthing must already be started). Comment=Opens Syncthing's Web UI in the default browser (Syncthing must already be started).
Exec=syncthing browser Exec=syncthing --browser-only
Icon=syncthing Icon=syncthing
Terminal=false Terminal=false
Type=Application Type=Application
+1 -1
View File
@@ -7,7 +7,7 @@ StartLimitBurst=4
[Service] [Service]
User=%i User=%i
ExecStart=/usr/bin/syncthing serve --no-browser --no-restart ExecStart=/usr/bin/syncthing serve --no-browser --no-restart --logflags=0
Restart=on-failure Restart=on-failure
RestartSec=1 RestartSec=1
SuccessExitStatus=3 4 SuccessExitStatus=3 4
+1 -1
View File
@@ -18,4 +18,4 @@ env STNORESTART=yes
respawn respawn
# the syncthing command Upstart is to execute when it is started up # the syncthing command Upstart is to execute when it is started up
exec $SYNCTHING_EXE --no-browser exec $SYNCTHING_EXE -no-browser
+31 -51
View File
@@ -1,70 +1,68 @@
module github.com/syncthing/syncthing module github.com/syncthing/syncthing
go 1.24.0 go 1.23.0
require ( require (
github.com/AudriusButkevicius/recli v0.0.7 github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1
github.com/alecthomas/kong v1.12.1 github.com/alecthomas/kong v1.11.0
github.com/aws/aws-sdk-go v1.55.8 github.com/aws/aws-sdk-go v1.55.7
github.com/calmh/incontainer v1.0.0 github.com/calmh/incontainer v1.0.0
github.com/calmh/xdr v1.2.0 github.com/calmh/xdr v1.2.0
github.com/ccding/go-stun v0.1.5 github.com/ccding/go-stun v0.1.5
github.com/coreos/go-semver v0.3.1 github.com/chmduquesne/rollinghash v4.0.0+incompatible
github.com/d4l3k/messagediff v1.2.1 github.com/d4l3k/messagediff v1.2.1
github.com/getsentry/raven-go v0.2.0 github.com/getsentry/raven-go v0.2.0
github.com/go-ldap/ldap/v3 v3.4.11 github.com/go-ldap/ldap/v3 v3.4.11
github.com/gobwas/glob v0.2.3 github.com/gobwas/glob v0.2.3
github.com/gofrs/flock v0.12.1 github.com/gofrs/flock v0.12.1
github.com/greatroar/blobloom v0.8.0
github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/jackpal/gateway v1.0.16 github.com/jackpal/gateway v1.0.16
github.com/jackpal/go-nat-pmp v1.0.2 github.com/jackpal/go-nat-pmp v1.0.2
github.com/jmoiron/sqlx v1.4.0
github.com/julienschmidt/httprouter v1.3.0 github.com/julienschmidt/httprouter v1.3.0
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/maruel/panicparse/v2 v2.5.0 github.com/maruel/panicparse/v2 v2.5.0
github.com/mattn/go-sqlite3 v1.14.31 github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2
github.com/maxmind/geoipupdate/v6 v6.1.0 github.com/maxmind/geoipupdate/v6 v6.1.0
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
github.com/oschwald/geoip2-golang v1.13.0 github.com/oschwald/geoip2-golang v1.11.0
github.com/pierrec/lz4/v4 v4.1.22 github.com/pierrec/lz4/v4 v4.1.22
github.com/prometheus/client_golang v1.23.0 github.com/prometheus/client_golang v1.22.0
github.com/puzpuzpuz/xsync/v3 v3.5.1 github.com/puzpuzpuz/xsync/v3 v3.5.1
github.com/quic-go/quic-go v0.52.0 github.com/quic-go/quic-go v0.52.0
github.com/rabbitmq/amqp091-go v1.10.0 github.com/rabbitmq/amqp091-go v1.10.0
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9
github.com/shirou/gopsutil/v4 v4.25.6 // https://github.com/shirou/gopsutil/issues/1898 github.com/shirou/gopsutil/v4 v4.25.4
github.com/syncthing/notify v0.0.0-20250528144937-c7027d4f7465 github.com/syncthing/notify v0.0.0-20250528144937-c7027d4f7465
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
github.com/thejerf/suture/v4 v4.0.6 github.com/thejerf/suture/v4 v4.0.6
github.com/urfave/cli v1.22.17 github.com/urfave/cli v1.22.16
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
github.com/willabides/kongplete v0.4.0 github.com/willabides/kongplete v0.4.0
github.com/wlynxg/anet v0.0.5
go.uber.org/automaxprocs v1.6.0 go.uber.org/automaxprocs v1.6.0
golang.org/x/crypto v0.41.0 golang.org/x/crypto v0.38.0
golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 golang.org/x/net v0.40.0
golang.org/x/net v0.43.0 golang.org/x/sys v0.33.0
golang.org/x/sys v0.35.0 golang.org/x/text v0.25.0
golang.org/x/text v0.28.0 golang.org/x/time v0.11.0
golang.org/x/time v0.12.0 golang.org/x/tools v0.33.0
google.golang.org/protobuf v1.36.7 google.golang.org/protobuf v1.36.6
modernc.org/sqlite v1.38.2 sigs.k8s.io/yaml v1.4.0
sigs.k8s.io/yaml v1.6.0
) )
require ( require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/coreos/go-semver v0.3.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/ebitengine/purego v0.8.3 // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
@@ -76,10 +74,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.3 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/nxadm/tail v1.4.11 // indirect github.com/nxadm/tail v1.4.11 // indirect
github.com/onsi/ginkgo/v2 v2.23.4 // indirect github.com/onsi/ginkgo/v2 v2.23.4 // indirect
github.com/oschwald/maxminddb-golang v1.13.1 // indirect github.com/oschwald/maxminddb-golang v1.13.1 // indirect
@@ -87,36 +82,21 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/posener/complete v1.2.3 // indirect github.com/posener/complete v1.2.3 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab // indirect github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.10.0 // indirect github.com/stretchr/testify v1.10.0 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.10.0 // indirect github.com/tklauser/numcpus v0.9.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/mock v0.5.2 // indirect go.uber.org/mock v0.5.2 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/mod v0.24.0 // indirect
golang.org/x/mod v0.27.0 // indirect golang.org/x/sync v0.14.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/tools v0.36.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.66.3 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
) )
// https://github.com/gobwas/glob/pull/55 // https://github.com/gobwas/glob/pull/55
replace github.com/gobwas/glob v0.2.3 => github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b replace github.com/gobwas/glob v0.2.3 => github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b
// https://github.com/mattn/go-sqlite3/pull/1338
replace github.com/mattn/go-sqlite3 v1.14.31 => github.com/calmh/go-sqlite3 v1.14.32-0.20250812195006-80712c77b76a
tool (
github.com/calmh/xdr/cmd/genxdr
github.com/maxbrunsfeld/counterfeiter/v6
golang.org/x/tools/cmd/goimports
)
+69 -117
View File
@@ -1,38 +1,34 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f h1:GmH5lT+moM7PbAJFBq57nH9WJ+wRnBXr/tyaYWbSAx8=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f/go.mod h1:Nhfib1j/VFnLrXL9cHgA+/n2O6P5THuWelOnbfPNd78=
github.com/AudriusButkevicius/recli v0.0.7 h1:9zjbYlTupi+W5SJXm2cR2sV2mJAIg1sIfDcsW7hrkPM= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
github.com/AudriusButkevicius/recli v0.0.7/go.mod h1:Nhfib1j/VFnLrXL9cHgA+/n2O6P5THuWelOnbfPNd78= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 h1:Wc1ml6QlJs2BHQ/9Bqu1jiyggbsSjramq2oUmp5WeIo= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1 h1:/Zt+cDPnpC3OVDm/JKLOs7M2DKmLRIIp3XIx9pHHiig= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.1/go.mod h1:Ng3urmn6dYe8gnbCMoHHVl5APYz2txho3koEkV2o2HA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 h1:FwladfywkNirM+FZYLBR2kBz5C8Tg0fw5w5Y7meRXWI= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2/go.mod h1:vv5Ad0RrIoT1lJFdWBZwt4mB1+j+V8DUroixmKDTCdk= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= 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/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/kong v1.12.1 h1:iq6aMJDcFYP9uFrLdsiZQ2ZMmcshduyGv4Pek0MQPW0= github.com/alecthomas/kong v1.11.0 h1:y++1gI7jf8O7G7l4LZo5ASFhrhJvzc+WgF/arranEmM=
github.com/alecthomas/kong v1.12.1/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU= github.com/alecthomas/kong v1.11.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE=
github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b h1:Fjm4GuJ+TGMgqfGHN42IQArJb77CfD/mAwLbDUoJe6g= github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b h1:Fjm4GuJ+TGMgqfGHN42IQArJb77CfD/mAwLbDUoJe6g=
github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b/go.mod h1:91K7jfEsgJSyfSrX+gmrRfZMtntx6JsHolWubGXDopg= github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b/go.mod h1:91K7jfEsgJSyfSrX+gmrRfZMtntx6JsHolWubGXDopg=
github.com/calmh/go-sqlite3 v1.14.32-0.20250812195006-80712c77b76a h1:lTe5qJApKNO+zZCa3/P/7UxM4c58CXWOegv9eODPWvs=
github.com/calmh/go-sqlite3 v1.14.32-0.20250812195006-80712c77b76a/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/calmh/incontainer v1.0.0 h1:g2cTUtZuFGmMGX8GoykPkN1Judj2uw8/3/aEtq4Z/rg= github.com/calmh/incontainer v1.0.0 h1:g2cTUtZuFGmMGX8GoykPkN1Judj2uw8/3/aEtq4Z/rg=
github.com/calmh/incontainer v1.0.0/go.mod h1:eOhqnw15c9X+4RNBe0W3HlUZFfX16O0EDsCOInTndHY= github.com/calmh/incontainer v1.0.0/go.mod h1:eOhqnw15c9X+4RNBe0W3HlUZFfX16O0EDsCOInTndHY=
github.com/calmh/xdr v1.2.0 h1:GaGSNH4ZDw9kNdYqle6+RcAENiaQ8/611Ok+jQbBEeU= github.com/calmh/xdr v1.2.0 h1:GaGSNH4ZDw9kNdYqle6+RcAENiaQ8/611Ok+jQbBEeU=
@@ -45,22 +41,22 @@ github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chmduquesne/rollinghash v4.0.0+incompatible h1:hnREQO+DXjqIw3rUTzWN7/+Dpw+N5Um8zpKV0JOEgbo=
github.com/chmduquesne/rollinghash v4.0.0+incompatible/go.mod h1:Uc2I36RRfTAf7Dge82bi3RU0OQUmXT9iweIcPqvr8A0=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 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/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/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 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= github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
@@ -78,15 +74,13 @@ github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@@ -102,6 +96,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
@@ -110,6 +105,8 @@ github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4 h1:gD0vax+4I+mAj+jECh
github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 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/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/greatroar/blobloom v0.8.0 h1:I9RlEkfqK9/6f1v9mFmDYegDQ/x0mISCpiNpAm23Pt4=
github.com/greatroar/blobloom v0.8.0/go.mod h1:mjMJ1hh1wjGVfr93QIHJ6FfDNVrA0IELv8OvMHJxHKs=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -144,8 +141,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
@@ -158,25 +153,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0=
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/maruel/panicparse/v2 v2.5.0 h1:yCtuS0FWjfd0RTYMXGpDvWcb0kINm8xJGu18/xMUh00= github.com/maruel/panicparse/v2 v2.5.0 h1:yCtuS0FWjfd0RTYMXGpDvWcb0kINm8xJGu18/xMUh00=
github.com/maruel/panicparse/v2 v2.5.0/go.mod h1:DA2fDiBk63bKfBf4CVZP9gb4fuvzdPbLDsSI873hweQ= github.com/maruel/panicparse/v2 v2.5.0/go.mod h1:DA2fDiBk63bKfBf4CVZP9gb4fuvzdPbLDsSI873hweQ=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2 h1:yVCLo4+ACVroOEr4iFU1iH46Ldlzz2rTuu18Ra7M8sU=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2/go.mod h1:VzB2VoMh1Y32/QqDfg9ZJYHj99oM4LiGtqPZydTiQSQ=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.3 h1:Eaq36EIyJNp7b3qDhjV7jmDVq/yPeW2v4pTqzGbOGB4=
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.3/go.mod h1:6KKUoQBZBW6PDXJtNfqeEjPXMj/ITTk+cWK9t9uS5+E=
github.com/maxmind/geoipupdate/v6 v6.1.0 h1:sdtTHzzQNJlXF5+fd/EoPTucRHyMonYt/Cok8xzzfqA= github.com/maxmind/geoipupdate/v6 v6.1.0 h1:sdtTHzzQNJlXF5+fd/EoPTucRHyMonYt/Cok8xzzfqA=
github.com/maxmind/geoipupdate/v6 v6.1.0/go.mod h1:cZYCDzfMzTY4v6dKRdV7KTB6SStxtn3yFkiJ1btTGGc= github.com/maxmind/geoipupdate/v6 v6.1.0/go.mod h1:cZYCDzfMzTY4v6dKRdV7KTB6SStxtn3yFkiJ1btTGGc=
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 h1:cUVxyR+UfmdEAZGJ8IiKld1O0dbGotEnkMolG5hfMSY= github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 h1:cUVxyR+UfmdEAZGJ8IiKld1O0dbGotEnkMolG5hfMSY=
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75/go.mod h1:pBbZyGwC5i16IBkjVKoy/sznA8jPD/K9iedwe1ESE6w= github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75/go.mod h1:pBbZyGwC5i16IBkjVKoy/sznA8jPD/K9iedwe1ESE6w=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
@@ -193,10 +181,10 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU=
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/oschwald/geoip2-golang v1.13.0 h1:Q44/Ldc703pasJeP5V9+aFSZFmBN7DKHbNsSFzQATJI= github.com/oschwald/geoip2-golang v1.11.0 h1:hNENhCn1Uyzhf9PTmquXENiWS6AlxAEnBII6r8krA3w=
github.com/oschwald/geoip2-golang v1.13.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo= github.com/oschwald/geoip2-golang v1.11.0/go.mod h1:P9zG+54KPEFOliZ29i7SeYZ/GM6tfEL+rgSn03hYuUo=
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE= github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8= github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
@@ -214,14 +202,14 @@ 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/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 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg= github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/quic-go/quic-go v0.52.0 h1:/SlHrCRElyaU6MaEPKqKr9z83sBg2v4FLLvWM+Z47pA= github.com/quic-go/quic-go v0.52.0 h1:/SlHrCRElyaU6MaEPKqKr9z83sBg2v4FLLvWM+Z47pA=
@@ -230,8 +218,6 @@ github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzuk
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o= github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg= github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg=
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab h1:ZjX6I48eZSFetPb41dHudEyVr5v953N15TsNZXlkcWY= github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab h1:ZjX6I48eZSFetPb41dHudEyVr5v953N15TsNZXlkcWY=
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab/go.mod h1:/PfPXh0EntGc3QAAyUaviy4S9tzy4Zp0e2ilq4voC6E= github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab/go.mod h1:/PfPXh0EntGc3QAAyUaviy4S9tzy4Zp0e2ilq4voC6E=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
@@ -240,8 +226,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs= github.com/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw=
github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -253,6 +239,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syncthing/notify v0.0.0-20250528144937-c7027d4f7465 h1:yhxdTGmFkAM2TFA65c3NgGwpnIkUM8oVqPX2e9S7IVg= github.com/syncthing/notify v0.0.0-20250528144937-c7027d4f7465 h1:yhxdTGmFkAM2TFA65c3NgGwpnIkUM8oVqPX2e9S7IVg=
@@ -261,19 +248,17 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
github.com/thejerf/suture/v4 v4.0.6 h1:QsuCEsCqb03xF9tPAsWAj8QOAJBgQI1c0VqJNaingg8= github.com/thejerf/suture/v4 v4.0.6 h1:QsuCEsCqb03xF9tPAsWAj8QOAJBgQI1c0VqJNaingg8=
github.com/thejerf/suture/v4 v4.0.6/go.mod h1:gu9Y4dXNUWFrByqRt30Rm9/UZ0wzRSt9AJS6xu/ZGxU= github.com/thejerf/suture/v4 v4.0.6/go.mod h1:gu9Y4dXNUWFrByqRt30Rm9/UZ0wzRSt9AJS6xu/ZGxU=
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo=
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= 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.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.17 h1:SYzXoiPfQjHBbkYxbew5prZHS1TOLT3ierW8SYLqtVQ= github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ=
github.com/urfave/cli v1.22.17/go.mod h1:b0ht0aqgH/6pBYzzxURyrM4xXNgsoT/n2ZzwQiEhNVo= 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 h1:okhMind4q9H1OxF44gNegWkiP4H/gsTFLalHFa4OOUI=
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0/go.mod h1:TTbGUfE+cXXceWtbTHq6lqcTvYPBKLNejBEbnUsQJtU= github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0/go.mod h1:TTbGUfE+cXXceWtbTHq6lqcTvYPBKLNejBEbnUsQJtU=
github.com/willabides/kongplete v0.4.0 h1:eivXxkp5ud5+4+NVN9e4goxC5mSh3n1RHov+gsblM2g= github.com/willabides/kongplete v0.4.0 h1:eivXxkp5ud5+4+NVN9e4goxC5mSh3n1RHov+gsblM2g=
github.com/willabides/kongplete v0.4.0/go.mod h1:0P0jtWD9aTsqPSUAl4de35DLghrr57XcayPyvqSi2X8= github.com/willabides/kongplete v0.4.0/go.mod h1:0P0jtWD9aTsqPSUAl4de35DLghrr57XcayPyvqSi2X8=
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
@@ -283,20 +268,14 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 h1:3yiSh9fhy5/RhCSntf4Sy0Tnx50DmMpQ4MQdKKk4yg4=
golang.org/x/exp v0.0.0-20250811191247-51f88131bc50/go.mod h1:rT6SFzZ7oxADUDx58pcaKFTcZ+inxAa9fTrYx/uVYwg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -305,13 +284,13 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -333,24 +312,23 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -364,8 +342,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.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-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.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -381,31 +359,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM=
modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ=
modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek=
modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
+1 -1
View File
@@ -370,7 +370,7 @@
"Show diff with previous version": "أظهر الفرق مقارنةً بالنسخة السابقة", "Show diff with previous version": "أظهر الفرق مقارنةً بالنسخة السابقة",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "يُعرَض بدلا من المُعرِّف ضمن العناقيد. سيُروَّج للأجهزة الأخرى على أنه اسم أساسي محتمل.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "يُعرَض بدلا من المُعرِّف ضمن العناقيد. سيُروَّج للأجهزة الأخرى على أنه اسم أساسي محتمل.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "يُعرَض بدلا من المُعرِّف ضمن العناقيد. إذا تُرك فارغا، سيُحدَّث إلى الاسم المختار من قِبَل الجهاز.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "يُعرَض بدلا من المُعرِّف ضمن العناقيد. إذا تُرك فارغا، سيُحدَّث إلى الاسم المختار من قِبَل الجهاز.",
"Shut Down": "إغلاق", "Shutdown": "إغلاق",
"Shutdown Complete": "أُغلِق", "Shutdown Complete": "أُغلِق",
"Simple": "بسيط", "Simple": "بسيط",
"Simple File Versioning": "التقسيم البسيط لإصدارات الملفات", "Simple File Versioning": "التقسيم البسيط لإصدارات الملفات",
+1 -1
View File
@@ -152,7 +152,7 @@
"Show ID": "Паказаць ID", "Show ID": "Паказаць ID",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
"Shut Down": "Выключыць", "Shutdown": "Выключыць",
"Shutdown Complete": "Выключэньне завершанае", "Shutdown Complete": "Выключэньне завершанае",
"Simple File Versioning": "Простае захоўваньне вэрсій", "Simple File Versioning": "Простае захоўваньне вэрсій",
"Single level wildcard (matches within a directory only)": "Single level wildcard (matches within a directory only)", "Single level wildcard (matches within a directory only)": "Single level wildcard (matches within a directory only)",
+2 -5
View File
@@ -82,7 +82,6 @@
"Custom Range": "В периода", "Custom Range": "В периода",
"Danger!": "Опасност!", "Danger!": "Опасност!",
"Database Location": "Местоположение на хранилището", "Database Location": "Местоположение на хранилището",
"Debug": "Отстраняване на дефекти",
"Debugging Facilities": "Отстраняване на дефекти", "Debugging Facilities": "Отстраняване на дефекти",
"Default": "По подразбиране", "Default": "По подразбиране",
"Default Configuration": "Настройки по подразбиране", "Default Configuration": "Настройки по подразбиране",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Ограничение при изтегляне (КиБ/с)", "Incoming Rate Limit (KiB/s)": "Ограничение при изтегляне (КиБ/с)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Неправилни настройки могат да повредят файлове и да попречат на синхронизирането.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Неправилни настройки могат да повредят файлове и да попречат на синхронизирането.",
"Incorrect user name or password.": "Грешно потребителско име или парола.", "Incorrect user name or password.": "Грешно потребителско име или парола.",
"Info": "Сведения",
"Internally used paths:": "Вътрешно използвани пътища:", "Internally used paths:": "Вътрешно използвани пътища:",
"Introduced By": "Предложено от", "Introduced By": "Предложено от",
"Introducer": "Поръчител", "Introducer": "Поръчител",
@@ -229,7 +227,6 @@
"Learn more": "Научете повече", "Learn more": "Научете повече",
"Learn more at {%url%}": "Научете повече на {{url}}", "Learn more at {%url%}": "Научете повече на {{url}}",
"Limit": "Ограничение", "Limit": "Ограничение",
"Limit Bandwidth in LAN": "Огранич. на скоростта в местната мрежа",
"Listener Failures": "Грешки при очакване на връзка", "Listener Failures": "Грешки при очакване на връзка",
"Listener Status": "Очакване на връзка", "Listener Status": "Очакване на връзка",
"Listeners": "Очакване на връзка", "Listeners": "Очакване на връзка",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Показване на разликите с предходната версия", "Show diff with previous version": "Показване на разликите с предходната версия",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "В списъка на устройствата се показва вместо идентификатор. Ще бъде предложено на другите устройства като име по подразбиране.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "В списъка на устройствата се показва вместо идентификатор. Ще бъде предложено на другите устройства като име по подразбиране.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "В списъка на устройствата се показва вместо идентификатор. Ако бъде оставено празно ще бъде променено на името, което носи устройството.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "В списъка на устройствата се показва вместо идентификатор. Ако бъде оставено празно ще бъде променено на името, което носи устройството.",
"Shut Down": "Изключване", "Shutdown": "Изключване",
"Shutdown Complete": "Спирането завършено", "Shutdown Complete": "Спирането завършено",
"Simple": "Обикновени", "Simple": "Обикновени",
"Simple File Versioning": "Обикновени версии", "Simple File Versioning": "Обикновени версии",
@@ -531,7 +528,7 @@
"You have unsaved changes. Do you really want to discard them?": "Има незапазени промени. Желаете ли да се откажете от тях?", "You have unsaved changes. Do you really want to discard them?": "Има незапазени промени. Желаете ли да се откажете от тях?",
"You must keep at least one version.": "Необходимо е да запазите поне една версия.", "You must keep at least one version.": "Необходимо е да запазите поне една версия.",
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "Никога не трябва да променяте нищо в папка от вида „{{receiveEncrypted}}“.", "You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "Никога не трябва да променяте нищо в папка от вида „{{receiveEncrypted}}“.",
"Your SMS app should open to let you choose the recipient and send it from your own number.": "Приложението за SMS би трябвало да се отвори, да ви даде възможност да изберете получател, на когото да изпратите съобщението от вашия телефонен номер.", "Your SMS app should open to let you choose the recipient and send it from your own number.": "Приложението за SMS би трябвало да се отвори, да ви даде възможност да изберете получател, за да изпратите съобщението от вашия телефонен номер.",
"Your email app should open to let you choose the recipient and send it from your own address.": "Пощенският клиент би трябвало да се отвори, да ви даде възможност да изберете получател, за да изпратите съобщението от вашия адрес за електронна поща.", "Your email app should open to let you choose the recipient and send it from your own address.": "Пощенският клиент би трябвало да се отвори, да ви даде възможност да изберете получател, за да изпратите съобщението от вашия адрес за електронна поща.",
"days": "дни", "days": "дни",
"deleted": "премахнато", "deleted": "премахнато",
+1 -3
View File
@@ -27,7 +27,6 @@
"Allowed Networks": "Xarxes permeses", "Allowed Networks": "Xarxes permeses",
"Alphabetic": "Alfabètic", "Alphabetic": "Alfabètic",
"Altered by ignoring deletes.": "S'ha alterat ignorant les supressions.", "Altered by ignoring deletes.": "S'ha alterat ignorant les supressions.",
"Always turned on when the folder type is \"{%foldertype%}\".": "Sempre activat quan el tipus de carpeta és \"{{foldertype}}\".",
"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.": "Una ordre externa gestiona la versió. Ha d'eliminar el fitxer de la carpeta compartida. Si el camí a l'aplicació conté espais, s'ha de citar.", "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.": "Una ordre externa gestiona la versió. Ha d'eliminar el fitxer de la carpeta compartida. Si el camí a l'aplicació conté espais, s'ha de citar.",
"Anonymous Usage Reporting": "Informe anònim d'ús", "Anonymous Usage Reporting": "Informe anònim d'ús",
"Anonymous usage report format has changed. Would you like to move to the new format?": "El format de l'informe d'ús anònim ha canviat. Voleu canviar a aquest nou format?", "Anonymous usage report format has changed. Would you like to move to the new format?": "El format de l'informe d'ús anònim ha canviat. Voleu canviar a aquest nou format?",
@@ -53,7 +52,6 @@
"Body:": "Cos de text:", "Body:": "Cos de text:",
"Bugs": "Errors (Bugs)", "Bugs": "Errors (Bugs)",
"Cancel": "Cancel·la", "Cancel": "Cancel·la",
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "No es pot habilitar quan el tipus de carpeta és \"{{foldertype}}\".",
"Changelog": "Historial de canvis", "Changelog": "Historial de canvis",
"Clean out after": "Netejar després", "Clean out after": "Netejar després",
"Cleaning Versions": "Netejant versions", "Cleaning Versions": "Netejant versions",
@@ -370,7 +368,7 @@
"Show diff with previous version": "Mostra la diferència amb la versió anterior", "Show diff with previous version": "Mostra la diferència amb la versió anterior",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrat en comptes del ID del Node en l'estat del cluster. Serà advertit als altres dispositius com un nom opcional per defecte.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrat en comptes del ID del Node en l'estat del cluster. Serà advertit als altres dispositius com un nom opcional per defecte.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrat en comptes del ID del Node en l'estat del cluster. S'actualitzarà al nom del dispositiu si es deixa buit.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrat en comptes del ID del Node en l'estat del cluster. S'actualitzarà al nom del dispositiu si es deixa buit.",
"Shut Down": "Apaga", "Shutdown": "Apaga",
"Shutdown Complete": "Apagat complet", "Shutdown Complete": "Apagat complet",
"Simple": "Simple", "Simple": "Simple",
"Simple File Versioning": "Versionat de Fitxers Senzill", "Simple File Versioning": "Versionat de Fitxers Senzill",
@@ -353,7 +353,7 @@
"Show diff with previous version": "Mostrar les diferències amb la versió prèvia", "Show diff with previous version": "Mostrar les diferències amb la versió prèvia",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrat en lloc de l'ID del dispositiu en l'estat del grup (cluster). S'anunciarà als altres dispositius com el nom opcional per defecte.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrat en lloc de l'ID del dispositiu en l'estat del grup (cluster). S'anunciarà als altres dispositius com el nom opcional per defecte.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrat en lloc de l'ID del dispositiu en l'estat del grup (cluster). S'actualitzarà al nom que el dispositiu anuncia si es deixa buit.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrat en lloc de l'ID del dispositiu en l'estat del grup (cluster). S'actualitzarà al nom que el dispositiu anuncia si es deixa buit.",
"Shut Down": "Apagar", "Shutdown": "Apagar",
"Shutdown Complete": "Apagar completament", "Shutdown Complete": "Apagar completament",
"Simple": "Senzill", "Simple": "Senzill",
"Simple File Versioning": "Versionat de fitxers senzill", "Simple File Versioning": "Versionat de fitxers senzill",
+1 -1
View File
@@ -360,7 +360,7 @@
"Show diff with previous version": "Ukázat rozdíl oproti předchozí verzi", "Show diff with previous version": "Ukázat rozdíl oproti předchozí verzi",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Zobrazeno místo identifikátoru zařízení na náhledu stavu clusteru. Bude odesíláno ostatním zařízením jako výchozí název zařízení.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Zobrazeno místo identifikátoru zařízení na náhledu stavu clusteru. Bude odesíláno ostatním zařízením jako výchozí název zařízení.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Zobrazeno místo identifikátoru zařízení na náhledu stavu clusteru. Pokud nebude vyplněno, bude nastaveno na název, který zařízení odesílá.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Zobrazeno místo identifikátoru zařízení na náhledu stavu clusteru. Pokud nebude vyplněno, bude nastaveno na název, který zařízení odesílá.",
"Shut Down": "Vypnout", "Shutdown": "Vypnout",
"Shutdown Complete": "Vypnutí dokončeno", "Shutdown Complete": "Vypnutí dokončeno",
"Simple": "Jednoduché", "Simple": "Jednoduché",
"Simple File Versioning": "Jednoduchá správa verzí souborů", "Simple File Versioning": "Jednoduchá správa verzí souborů",
+1 -1
View File
@@ -368,7 +368,7 @@
"Show diff with previous version": "Vis forskelle fra tidligere version", "Show diff with previous version": "Vis forskelle fra tidligere version",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vises i stedet for enheds-ID i klyngestatus. Vil blive sendt til andre enheder som valgfrit standardnavn.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vises i stedet for enheds-ID i klyngestatus. Vil blive sendt til andre enheder som valgfrit standardnavn.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vises i stedet for enheds-ID i klyngestatus. Vil blive opdateret til det navn, som enheden sender, hvis det ikke er udfyldt.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vises i stedet for enheds-ID i klyngestatus. Vil blive opdateret til det navn, som enheden sender, hvis det ikke er udfyldt.",
"Shut Down": "Luk ned", "Shutdown": "Luk ned",
"Shutdown Complete": "Nedlukning fuldført", "Shutdown Complete": "Nedlukning fuldført",
"Simple": "Enkel", "Simple": "Enkel",
"Simple File Versioning": "Simpel filversionering", "Simple File Versioning": "Simpel filversionering",
+4 -7
View File
@@ -61,7 +61,7 @@
"Click to see full identification string and QR code.": "Klicken, um die vollständige Kennung und den QR-Code anzuzeigen.", "Click to see full identification string and QR code.": "Klicken, um die vollständige Kennung und den QR-Code anzuzeigen.",
"Close": "Schließen", "Close": "Schließen",
"Command": "Befehl", "Command": "Befehl",
"Comment, when used at the start of a line": "Kommentar, wenn am Anfang der Zeile verwendet", "Comment, when used at the start of a line": "Kommentar, wenn am Anfang der Zeile verwendet.",
"Compression": "Komprimierung", "Compression": "Komprimierung",
"Configuration Directory": "Konfigurationsverzeichnis", "Configuration Directory": "Konfigurationsverzeichnis",
"Configuration File": "Konfigurationsdatei", "Configuration File": "Konfigurationsdatei",
@@ -82,7 +82,6 @@
"Custom Range": "Eigener Zeitraum", "Custom Range": "Eigener Zeitraum",
"Danger!": "Achtung!", "Danger!": "Achtung!",
"Database Location": "Datenbank-Speicherort", "Database Location": "Datenbank-Speicherort",
"Debug": "Debug",
"Debugging Facilities": "Debugging-Möglichkeiten", "Debugging Facilities": "Debugging-Möglichkeiten",
"Default": "Vorgabe", "Default": "Vorgabe",
"Default Configuration": "Vorgabekonfiguration", "Default Configuration": "Vorgabekonfiguration",
@@ -105,7 +104,7 @@
"Device Status": "Gerätestatus", "Device Status": "Gerätestatus",
"Device is untrusted, enter encryption password": "Gerät wird nicht vertraut, Verschlüsselungspasswort eingeben", "Device is untrusted, enter encryption password": "Gerät wird nicht vertraut, Verschlüsselungspasswort eingeben",
"Device rate limits": "Datenratenbegrenzungen fürs Gerät", "Device rate limits": "Datenratenbegrenzungen fürs Gerät",
"Device that last modified the item": "Gerät, welches das Element zuletzt geändert hat", "Device that last modified the item": "Gerät, das das Element zuletzt geändert hat",
"Devices": "Geräte", "Devices": "Geräte",
"Disable Crash Reporting": "Absturzmeldung deaktivieren", "Disable Crash Reporting": "Absturzmeldung deaktivieren",
"Disabled": "Deaktiviert", "Disabled": "Deaktiviert",
@@ -184,7 +183,7 @@
"GUI / API HTTPS Certificate": "GUI / API HTTPS-Zertifikat", "GUI / API HTTPS Certificate": "GUI / API HTTPS-Zertifikat",
"GUI Authentication Password": "Passwort für Zugang zur Benutzeroberfläche", "GUI Authentication Password": "Passwort für Zugang zur Benutzeroberfläche",
"GUI Authentication User": "Benutzername für Zugang zur Benutzeroberfläche", "GUI Authentication User": "Benutzername für Zugang zur Benutzeroberfläche",
"GUI Authentication: Set User and Password": "Authentifizierung für die Benutzeroberfläche: Geben Sie Benutzer und Passwort ein", "GUI Authentication: Set User and Password": "Authentifizierung für die Benutzeroberfläche: Geben Sie Benutzer und Passwort ein.",
"GUI Listen Address": "Adresse der Benutzeroberfläche", "GUI Listen Address": "Adresse der Benutzeroberfläche",
"GUI Override Directory": "GUI-Ersatz-Verzeichnis", "GUI Override Directory": "GUI-Ersatz-Verzeichnis",
"GUI Theme": "GUI-Design", "GUI Theme": "GUI-Design",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Eingehende Datenratenbegrenzung (KiB/s)", "Incoming Rate Limit (KiB/s)": "Eingehende Datenratenbegrenzung (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Eine falsche Konfiguration kann den Ordnerinhalt beschädigen und Syncthing in einen unausführbaren Zustand versetzen.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Eine falsche Konfiguration kann den Ordnerinhalt beschädigen und Syncthing in einen unausführbaren Zustand versetzen.",
"Incorrect user name or password.": "Falscher Benutzername oder Passwort.", "Incorrect user name or password.": "Falscher Benutzername oder Passwort.",
"Info": "Info",
"Internally used paths:": "Intern verwendete Pfade:", "Internally used paths:": "Intern verwendete Pfade:",
"Introduced By": "Verteilt von", "Introduced By": "Verteilt von",
"Introducer": "Verteilergerät", "Introducer": "Verteilergerät",
@@ -229,7 +227,6 @@
"Learn more": "Mehr erfahren", "Learn more": "Mehr erfahren",
"Learn more at {%url%}": "Erfahren Sie mehr unter {{url}}", "Learn more at {%url%}": "Erfahren Sie mehr unter {{url}}",
"Limit": "Limit", "Limit": "Limit",
"Limit Bandwidth in LAN": "Bandbreite im LAN begrenzen",
"Listener Failures": "Fehler bei Listener", "Listener Failures": "Fehler bei Listener",
"Listener Status": "Status der Listener", "Listener Status": "Status der Listener",
"Listeners": "Zuhörer", "Listeners": "Zuhörer",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Unterschied zur vorherigen Version anzeigen", "Show diff with previous version": "Unterschied zur vorherigen Version anzeigen",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wird anstelle der Gerätekennung im Verbundstatus angezeigt. Wird anderen Geräten als optionaler Standardname bekannt gegeben.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wird anstelle der Gerätekennung im Verbundstatus angezeigt. Wird anderen Geräten als optionaler Standardname bekannt gegeben.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wird anstelle der Gerätekennung im Verbundstatus angezeigt. Wird auf den Namen aktualisiert, den das Gerät anzeigt, wenn er leer bleibt.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wird anstelle der Gerätekennung im Verbundstatus angezeigt. Wird auf den Namen aktualisiert, den das Gerät anzeigt, wenn er leer bleibt.",
"Shut Down": "Herunterfahren", "Shutdown": "Herunterfahren",
"Shutdown Complete": "Vollständig heruntergefahren", "Shutdown Complete": "Vollständig heruntergefahren",
"Simple": "Einfach", "Simple": "Einfach",
"Simple File Versioning": "Einfache Dateiversionierung", "Simple File Versioning": "Einfache Dateiversionierung",
+1 -1
View File
@@ -368,7 +368,7 @@
"Show diff with previous version": "Εμφάνιση διαφορών με προηγούμενη έκδοση", "Show diff with previous version": "Εμφάνιση διαφορών με προηγούμενη έκδοση",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Θα φαίνεται αντί για την ταυτότητα της συσκευής στην προβολή της κατάστασης ολόκληρης της συστάδας. Θα γνωστοποιείται σαν το προαιρετικό όνομα της συσκευής.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Θα φαίνεται αντί για την ταυτότητα της συσκευής στην προβολή της κατάστασης ολόκληρης της συστάδας. Θα γνωστοποιείται σαν το προαιρετικό όνομα της συσκευής.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Θα φαίνεται αντί για την ταυτότητα της συσκευής στην προβολή της κατάστασης ολόκληρης της συστάδας. Θα ενημερώνεται αυτόματα αν αλλάξει το όνομα της συσκευής.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Θα φαίνεται αντί για την ταυτότητα της συσκευής στην προβολή της κατάστασης ολόκληρης της συστάδας. Θα ενημερώνεται αυτόματα αν αλλάξει το όνομα της συσκευής.",
"Shut Down": "Απενεργοποίηση", "Shutdown": "Απενεργοποίηση",
"Shutdown Complete": "Πλήρης απενεργοποίηση", "Shutdown Complete": "Πλήρης απενεργοποίηση",
"Simple": "Απλό", "Simple": "Απλό",
"Simple File Versioning": "Απλή τήρηση εκδόσεων", "Simple File Versioning": "Απλή τήρηση εκδόσεων",
+1 -1
View File
@@ -353,7 +353,7 @@
"Show diff with previous version": "Show diff with previous version", "Show diff with previous version": "Show diff with previous version",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
"Shut Down": "Shut Down", "Shutdown": "Shutdown",
"Shutdown Complete": "Shutdown Complete", "Shutdown Complete": "Shutdown Complete",
"Simple": "Simple", "Simple": "Simple",
"Simple File Versioning": "Simple File Versioning", "Simple File Versioning": "Simple File Versioning",
+1 -2
View File
@@ -227,7 +227,6 @@
"Learn more": "Learn more", "Learn more": "Learn more",
"Learn more at {%url%}": "Learn more at {{url}}", "Learn more at {%url%}": "Learn more at {{url}}",
"Limit": "Limit", "Limit": "Limit",
"Limit Bandwidth in LAN": "Limit Bandwidth in LAN",
"Listener Failures": "Listener Failures", "Listener Failures": "Listener Failures",
"Listener Status": "Listener Status", "Listener Status": "Listener Status",
"Listeners": "Listeners", "Listeners": "Listeners",
@@ -371,7 +370,7 @@
"Show diff with previous version": "Show diff with previous version", "Show diff with previous version": "Show diff with previous version",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
"Shut Down": "Shut Down", "Shutdown": "Shutdown",
"Shutdown Complete": "Shutdown Complete", "Shutdown Complete": "Shutdown Complete",
"Simple": "Simple", "Simple": "Simple",
"Simple File Versioning": "Simple File Versioning", "Simple File Versioning": "Simple File Versioning",
+1 -4
View File
@@ -82,7 +82,6 @@
"Custom Range": "Custom Range", "Custom Range": "Custom Range",
"Danger!": "Danger!", "Danger!": "Danger!",
"Database Location": "Database Location", "Database Location": "Database Location",
"Debug": "Debug",
"Debugging Facilities": "Debugging Facilities", "Debugging Facilities": "Debugging Facilities",
"Default": "Default", "Default": "Default",
"Default Configuration": "Default Configuration", "Default Configuration": "Default Configuration",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Incoming Rate Limit (KiB/s)", "Incoming Rate Limit (KiB/s)": "Incoming Rate Limit (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Incorrect configuration may damage your folder contents and render Syncthing inoperable.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Incorrect configuration may damage your folder contents and render Syncthing inoperable.",
"Incorrect user name or password.": "Incorrect user name or password.", "Incorrect user name or password.": "Incorrect user name or password.",
"Info": "Info",
"Internally used paths:": "Internally used paths:", "Internally used paths:": "Internally used paths:",
"Introduced By": "Introduced By", "Introduced By": "Introduced By",
"Introducer": "Introducer", "Introducer": "Introducer",
@@ -229,7 +227,6 @@
"Learn more": "Learn more", "Learn more": "Learn more",
"Learn more at {%url%}": "Learn more at {{url}}", "Learn more at {%url%}": "Learn more at {{url}}",
"Limit": "Limit", "Limit": "Limit",
"Limit Bandwidth in LAN": "Limit Bandwidth in LAN",
"Listener Failures": "Listener Failures", "Listener Failures": "Listener Failures",
"Listener Status": "Listener Status", "Listener Status": "Listener Status",
"Listeners": "Listeners", "Listeners": "Listeners",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Show diff with previous version", "Show diff with previous version": "Show diff with previous version",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
"Shut Down": "Shut Down", "Shutdown": "Shutdown",
"Shutdown Complete": "Shutdown Complete", "Shutdown Complete": "Shutdown Complete",
"Simple": "Simple", "Simple": "Simple",
"Simple File Versioning": "Simple File Versioning", "Simple File Versioning": "Simple File Versioning",
+1 -1
View File
@@ -258,7 +258,7 @@
"Show diff with previous version": "Montri diferenco kun antaŭa versio", "Show diff with previous version": "Montri diferenco kun antaŭa versio",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Montrita anstataŭ ID de Aparato en la statuso de la grupo. Estos anoncita al aliaj aparatoj kiel laŭvola defaŭlta nomo.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Montrita anstataŭ ID de Aparato en la statuso de la grupo. Estos anoncita al aliaj aparatoj kiel laŭvola defaŭlta nomo.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Montri anstataŭ ID de Aparato en la statuso de la grupo. Estos ĝisdatigita al la nomo de la aparato sciigante se ĝi estas lasita malplena.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Montri anstataŭ ID de Aparato en la statuso de la grupo. Estos ĝisdatigita al la nomo de la aparato sciigante se ĝi estas lasita malplena.",
"Shut Down": "Sistemfermo", "Shutdown": "Sistemfermo",
"Shutdown Complete": "Sistemfermo Tuta", "Shutdown Complete": "Sistemfermo Tuta",
"Simple File Versioning": "Simpla Versionado de Dosieroj", "Simple File Versioning": "Simpla Versionado de Dosieroj",
"Single level wildcard (matches within a directory only)": "Ununivela ĵokero (egalas nur ene de dosierujo)", "Single level wildcard (matches within a directory only)": "Ununivela ĵokero (egalas nur ene de dosierujo)",
+1 -1
View File
@@ -368,7 +368,7 @@
"Show diff with previous version": "Mostrar la diferencia con la versión anterior", "Show diff with previous version": "Mostrar la diferencia con la versión anterior",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Se muestra en lugar del ID del dispositivo en el estado del grupo (cluster). Se notificará a los otros dispositivos como nombre opcional por defecto.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Se muestra en lugar del ID del dispositivo en el estado del grupo (cluster). Se notificará a los otros dispositivos como nombre opcional por defecto.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Se muestra en lugar del ID del dispositivo en el estado del grupo (cluster). Se actualizará al nombre que el dispositivo anuncia si se deja vacío.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Se muestra en lugar del ID del dispositivo en el estado del grupo (cluster). Se actualizará al nombre que el dispositivo anuncia si se deja vacío.",
"Shut Down": "Apagar", "Shutdown": "Apagar",
"Shutdown Complete": "Apagar completamente", "Shutdown Complete": "Apagar completamente",
"Simple": "Sencillo", "Simple": "Sencillo",
"Simple File Versioning": "Versionado simple de fichero", "Simple File Versioning": "Versionado simple de fichero",
+6 -9
View File
@@ -1,22 +1,19 @@
{ {
"A device with that ID is already added.": "Sellise tunnusega seade on juba lisatud.", "A device with that ID is already added.": "Sellise seadme ID'ga seade on juba lisatud.",
"A negative number of days doesn't make sense.": "Negatiivne päevade arv ei ole loogiline.", "A negative number of days doesn't make sense.": "Negatiivne päevade arv ei ole loogiline.",
"API Key": "API võti", "API Key": "API Võti",
"About": "Rakenduse teave",
"Action": "Tegevus", "Action": "Tegevus",
"Actions": "Tegevused", "Actions": "Tegevused",
"Add": "Lisa", "Add": "Lisa",
"Add Device": "Lisa seade", "Add Device": "Lisa seade",
"Add Folder": "Lisa kaust", "Add Folder": "Lisa kaust",
"Add Remote Device": "Lisa kaugseade", "Add new folder?": "Lisa uus kaust?",
"Add new folder?": "Kas lisad uue kausta?",
"Address": "Aadress", "Address": "Aadress",
"Addresses": "Aadressid", "Addresses": "Aadressid",
"All Data": "Kõik andmed", "All Data": "Kõik andmed",
"All Time": "Kõik ajad", "All Time": "Kõik ajad",
"Allowed Networks": "Lubatud võrgud", "Allowed Networks": "Lubatud võrgud",
"Alphabetic": "Tähestikuline", "Alphabetic": "Tähestikuline",
"Apply": "Rakenda",
"Automatic upgrades": "Automaatsed uuendused", "Automatic upgrades": "Automaatsed uuendused",
"Be careful!": "Ettevaatust!", "Be careful!": "Ettevaatust!",
"Cancel": "Loobu", "Cancel": "Loobu",
@@ -50,7 +47,7 @@
"Folder Label": "Kausta Silt", "Folder Label": "Kausta Silt",
"Folder Type": "Kausta Tüüp", "Folder Type": "Kausta Tüüp",
"Folders": "Kaustad", "Folders": "Kaustad",
"GUI": "Kasutajaliides", "GUI": "GUI",
"GUI Authentication Password": "GUI Autentimise Salasõna", "GUI Authentication Password": "GUI Autentimise Salasõna",
"GUI Authentication User": "GUI Autentimise Kasutajatunnus", "GUI Authentication User": "GUI Autentimise Kasutajatunnus",
"GUI Theme": "GUI Teema", "GUI Theme": "GUI Teema",
@@ -78,7 +75,7 @@
"New Folder": "Uus Kaust", "New Folder": "Uus Kaust",
"Newest First": "Uusimad Ennem", "Newest First": "Uusimad Ennem",
"No": "Ei", "No": "Ei",
"OK": "Sobib", "OK": "OK",
"Oldest First": "Vanimad Ennem", "Oldest First": "Vanimad Ennem",
"Options": "Valikud", "Options": "Valikud",
"Outgoing Rate Limit (KiB/s)": "Väljuva Kiiruse Piirang (KiB/s)", "Outgoing Rate Limit (KiB/s)": "Väljuva Kiiruse Piirang (KiB/s)",
@@ -119,7 +116,7 @@
"The device ID cannot be blank.": "Seadme ID ei tohi olla tühi.", "The device ID cannot be blank.": "Seadme ID ei tohi olla tühi.",
"The folder ID cannot be blank.": "Kausta ID ei tohi olla tühi.", "The folder ID cannot be blank.": "Kausta ID ei tohi olla tühi.",
"The folder ID must be unique.": "Kausta ID peab olema unikaalne.", "The folder ID must be unique.": "Kausta ID peab olema unikaalne.",
"The folder path cannot be blank.": "Kausta asukoht ei tohi olla tühi.", "The folder path cannot be blank.": "Kausta asukoht ei tohi olla tühi!",
"The following items could not be synchronized.": "Järgnevaid üksusi ei õnnestunud sünkroniseerida.", "The following items could not be synchronized.": "Järgnevaid üksusi ei õnnestunud sünkroniseerida.",
"The maximum age must be a number and cannot be blank.": "Maksimaalne vanus peab olema arv ning ei tohi olla tühi.", "The maximum age must be a number and cannot be blank.": "Maksimaalne vanus peab olema arv ning ei tohi olla tühi.",
"Unknown": "Teadmata", "Unknown": "Teadmata",
+1 -1
View File
@@ -309,7 +309,7 @@
"Show diff with previous version": "Erakutsi aurreko bertsioarekiko aldeak", "Show diff with previous version": "Erakutsi aurreko bertsioarekiko aldeak",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Beste tresneri erakutsia izanen da, izen erabilgarri bat bezala", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Beste tresneri erakutsia izanen da, izen erabilgarri bat bezala",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Hutsa utzia balin bada, urrun den tresnak proposatu izenarekin aktualizatua izanen da", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Hutsa utzia balin bada, urrun den tresnak proposatu izenarekin aktualizatua izanen da",
"Shut Down": "Geldi", "Shutdown": "Geldi",
"Shutdown Complete": "Gelditua!", "Shutdown Complete": "Gelditua!",
"Simple File Versioning": "Bertsioen segitze sinplifikatua", "Simple File Versioning": "Bertsioen segitze sinplifikatua",
"Single level wildcard (matches within a directory only)": "Hein bakar bateko jokerra (karpetaren barnean bakarrik dagokiona)", "Single level wildcard (matches within a directory only)": "Hein bakar bateko jokerra (karpetaren barnean bakarrik dagokiona)",
+1 -1
View File
@@ -288,7 +288,7 @@
"Show diff with previous version": "Näytä muutokset edelliseen versioon", "Show diff with previous version": "Näytä muutokset edelliseen versioon",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Näytetään ryhmän tiedoissa laitteen ID:n sijaan. Ilmoitetaan muille laitteille vaihtoehtoisena oletusnimenä.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Näytetään ryhmän tiedoissa laitteen ID:n sijaan. Ilmoitetaan muille laitteille vaihtoehtoisena oletusnimenä.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Näytetään ryhmän tiedoissa laitteen ID:n sijaan. Tyhjä nimi päivitetään laitteen ilmoittamaksi nimeksi.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Näytetään ryhmän tiedoissa laitteen ID:n sijaan. Tyhjä nimi päivitetään laitteen ilmoittamaksi nimeksi.",
"Shut Down": "Sammuta", "Shutdown": "Sammuta",
"Shutdown Complete": "Sammutus valmis", "Shutdown Complete": "Sammutus valmis",
"Simple File Versioning": "Yksinkertainen tiedostoversiointi", "Simple File Versioning": "Yksinkertainen tiedostoversiointi",
"Single level wildcard (matches within a directory only)": "Yksitasoinen jokerimerkki (vaikuttaa vain kyseisen kansion sisällä)", "Single level wildcard (matches within a directory only)": "Yksitasoinen jokerimerkki (vaikuttaa vain kyseisen kansion sisällä)",
+1 -4
View File
@@ -82,7 +82,6 @@
"Custom Range": "Custom na Saklaw", "Custom Range": "Custom na Saklaw",
"Danger!": "Panganib!", "Danger!": "Panganib!",
"Database Location": "Lokasyon ng Database", "Database Location": "Lokasyon ng Database",
"Debug": "Debug",
"Debugging Facilities": "Mga Facility ng Pag-debug", "Debugging Facilities": "Mga Facility ng Pag-debug",
"Default": "Default", "Default": "Default",
"Default Configuration": "Default na Configuration", "Default Configuration": "Default na Configuration",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Rate Limit ng Papasok (KiB/s)", "Incoming Rate Limit (KiB/s)": "Rate Limit ng Papasok (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Maaring sirain ng maling pagsasaayos ang nilalaman ng iyong mga folder at gawing inoperable ang Syncthing.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Maaring sirain ng maling pagsasaayos ang nilalaman ng iyong mga folder at gawing inoperable ang Syncthing.",
"Incorrect user name or password.": "Maling user name o password.", "Incorrect user name or password.": "Maling user name o password.",
"Info": "Impormasyon",
"Internally used paths:": "Mga internal na ginamit na path:", "Internally used paths:": "Mga internal na ginamit na path:",
"Introduced By": "Ipinakilala Ni/Ng", "Introduced By": "Ipinakilala Ni/Ng",
"Introducer": "Tagapagpakilala", "Introducer": "Tagapagpakilala",
@@ -229,7 +227,6 @@
"Learn more": "Matuto pa", "Learn more": "Matuto pa",
"Learn more at {%url%}": "Matuto pa sa {{url}}", "Learn more at {%url%}": "Matuto pa sa {{url}}",
"Limit": "Limitasyon", "Limit": "Limitasyon",
"Limit Bandwidth in LAN": "Limitahan ang Bandwidth sa LAN",
"Listener Failures": "Mga Pagbibigo ng Listener", "Listener Failures": "Mga Pagbibigo ng Listener",
"Listener Status": "Status ng Listener", "Listener Status": "Status ng Listener",
"Listeners": "Mga Listener", "Listeners": "Mga Listener",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Ipakita ang diff sa nakaraang bersyon", "Show diff with previous version": "Ipakita ang diff sa nakaraang bersyon",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Ipinapakita sa halip na Device ID sa status ng cluster. Ia-advertise sa iba pang mga device bilang opsyonal na default na pangalan.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Ipinapakita sa halip na Device ID sa status ng cluster. Ia-advertise sa iba pang mga device bilang opsyonal na default na pangalan.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Ipinapakita sa halip na Device ID sa status ng cluster. Ia-update sa pangalan na ina-advertise ng device kung iiwanang walang laman.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Ipinapakita sa halip na Device ID sa status ng cluster. Ia-update sa pangalan na ina-advertise ng device kung iiwanang walang laman.",
"Shut Down": "I-shutdown", "Shutdown": "I-shutdown",
"Shutdown Complete": "Tapos na ang Shutdown", "Shutdown Complete": "Tapos na ang Shutdown",
"Simple": "Simple", "Simple": "Simple",
"Simple File Versioning": "Simpleng File Versioning", "Simple File Versioning": "Simpleng File Versioning",
+1 -1
View File
@@ -160,7 +160,7 @@
"Show QR": "Afficher l'image QR", "Show QR": "Afficher l'image QR",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Sera diffusé aux autres appareils comme nom convivial optionnel par défaut.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Sera diffusé aux autres appareils comme nom convivial optionnel par défaut.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Si laissé vide, il sera renseigné par le nom convivial proposé par l'appareil distant.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Si laissé vide, il sera renseigné par le nom convivial proposé par l'appareil distant.",
"Shut Down": "Arrêter", "Shutdown": "Arrêter",
"Shutdown Complete": "Arrêté !", "Shutdown Complete": "Arrêté !",
"Simple File Versioning": "Suivi simplifié des versions", "Simple File Versioning": "Suivi simplifié des versions",
"Single level wildcard (matches within a directory only)": "Joker à un seul niveau (correspond uniquement à lintérieur du répertoire)", "Single level wildcard (matches within a directory only)": "Joker à un seul niveau (correspond uniquement à lintérieur du répertoire)",
+2 -5
View File
@@ -82,7 +82,6 @@
"Custom Range": "Plage personnalisée", "Custom Range": "Plage personnalisée",
"Danger!": "Attention !", "Danger!": "Attention !",
"Database Location": "Emplacement de la base de données", "Database Location": "Emplacement de la base de données",
"Debug": "Débogage",
"Debugging Facilities": "Outils de débogage", "Debugging Facilities": "Outils de débogage",
"Default": "Par défaut", "Default": "Par défaut",
"Default Configuration": "Préférences pour les créations (non rétroactif)", "Default Configuration": "Préférences pour les créations (non rétroactif)",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Limite du débit de réception (Kio/s)", "Incoming Rate Limit (KiB/s)": "Limite du débit de réception (Kio/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Une configuration incorrecte peut créer des dommages dans vos répertoires et mettre Syncthing hors-service.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Une configuration incorrecte peut créer des dommages dans vos répertoires et mettre Syncthing hors-service.",
"Incorrect user name or password.": "Nom d'utilisateur ou mot de passe incorrect.", "Incorrect user name or password.": "Nom d'utilisateur ou mot de passe incorrect.",
"Info": "Informations",
"Internally used paths:": "Chemins utilisés en interne :", "Internally used paths:": "Chemins utilisés en interne :",
"Introduced By": "Introduit par", "Introduced By": "Introduit par",
"Introducer": "Appareil introducteur", "Introducer": "Appareil introducteur",
@@ -229,7 +227,6 @@
"Learn more": "En savoir plus", "Learn more": "En savoir plus",
"Learn more at {%url%}": "Si vous souhaitez en savoir plus, c'est ici (en anglais) : {{url}}", "Learn more at {%url%}": "Si vous souhaitez en savoir plus, c'est ici (en anglais) : {{url}}",
"Limit": "Limite", "Limit": "Limite",
"Limit Bandwidth in LAN": "Limiter la bande passante locale (LAN)",
"Listener Failures": "Échecs de l'écouteur", "Listener Failures": "Échecs de l'écouteur",
"Listener Status": "État de l'écouteur", "Listener Status": "État de l'écouteur",
"Listeners": "Écoute", "Listeners": "Écoute",
@@ -324,7 +321,7 @@
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Les versions préliminaires contiennent les dernières fonctionnalités et derniers correctifs. Elles sont identiques aux traditionnelles mises à jour bimensuelles.", "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Les versions préliminaires contiennent les dernières fonctionnalités et derniers correctifs. Elles sont identiques aux traditionnelles mises à jour bimensuelles.",
"Remote Devices": "Autres appareils", "Remote Devices": "Autres appareils",
"Remote GUI": "IHM distant", "Remote GUI": "IHM distant",
"Remove": "Enlever", "Remove": "Supprimer",
"Remove Device": "Supprimer l'appareil", "Remove Device": "Supprimer l'appareil",
"Remove Folder": "Supprimer le partage", "Remove Folder": "Supprimer le partage",
"Required identifier for the folder. Must be the same on all cluster devices.": "Identifiant du partage. Doit être le même sur tous les appareils concernés (généré aléatoirement, mais modifiable à la création, par exemple pour faire entrer un appareil dans un partage pré-existant actuellement non connecté mais dont on connaît déjà l'ID, ou s'il n'y a personne à l'autre bout pour vous inviter à y participer).", "Required identifier for the folder. Must be the same on all cluster devices.": "Identifiant du partage. Doit être le même sur tous les appareils concernés (généré aléatoirement, mais modifiable à la création, par exemple pour faire entrer un appareil dans un partage pré-existant actuellement non connecté mais dont on connaît déjà l'ID, ou s'il n'y a personne à l'autre bout pour vous inviter à y participer).",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Afficher les différences avec la version précédente", "Show diff with previous version": "Afficher les différences avec la version précédente",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Sera diffusé aux autres appareils comme nom convivial optionnel par défaut.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Sera diffusé aux autres appareils comme nom convivial optionnel par défaut.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Nom convivial local affiché à la place de l'ID de l'appareil dans la plupart des écrans. Si laissé vide, c'est le nom convivial local de l'appareil distant qui sera utilisé. (Modifiable ultérieurement).", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Nom convivial local affiché à la place de l'ID de l'appareil dans la plupart des écrans. Si laissé vide, c'est le nom convivial local de l'appareil distant qui sera utilisé. (Modifiable ultérieurement).",
"Shut Down": "Arrêter", "Shutdown": "Arrêter",
"Shutdown Complete": "Arrêt complet", "Shutdown Complete": "Arrêt complet",
"Simple": "Suivi simplifié", "Simple": "Suivi simplifié",
"Simple File Versioning": "Suivi simplifié des versions", "Simple File Versioning": "Suivi simplifié des versions",
+1 -1
View File
@@ -312,7 +312,7 @@
"Show diff with previous version": "Ferskil (diff) mei de foarige ferzje sjen litte", "Show diff with previous version": "Ferskil (diff) mei de foarige ferzje sjen litte",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wurd ynstee fan apparaat-ID sjen litten by de bondeltastân. Wurd nei oare apparaten advertearre as in mooglike standertnamme.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wurd ynstee fan apparaat-ID sjen litten by de bondeltastân. Wurd nei oare apparaten advertearre as in mooglike standertnamme.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wurd yn de bondeltastân sjen litten ynstee fan apparaat-ID. Wannear't leech litten wurd, wurd it fernijt nei de namme die it apparaat útstjoert.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wurd yn de bondeltastân sjen litten ynstee fan apparaat-ID. Wannear't leech litten wurd, wurd it fernijt nei de namme die it apparaat útstjoert.",
"Shut Down": "Ofslute", "Shutdown": "Ofslute",
"Shutdown Complete": "Ofsluten klear", "Shutdown Complete": "Ofsluten klear",
"Simple File Versioning": "Ienfâldich triemferzjebehear", "Simple File Versioning": "Ienfâldich triemferzjebehear",
"Single level wildcard (matches within a directory only)": "Inkel-nivo jokerteken (wildcard) (fergeliket allinnich binnen in map)", "Single level wildcard (matches within a directory only)": "Inkel-nivo jokerteken (wildcard) (fergeliket allinnich binnen in map)",
+1 -4
View File
@@ -82,7 +82,6 @@
"Custom Range": "Raon Saincheaptha", "Custom Range": "Raon Saincheaptha",
"Danger!": "Contúirt!", "Danger!": "Contúirt!",
"Database Location": "Suíomh an Bhunachair Sonraí", "Database Location": "Suíomh an Bhunachair Sonraí",
"Debug": "Dífhabhtú",
"Debugging Facilities": "Áiseanna Dífhabhtaithe", "Debugging Facilities": "Áiseanna Dífhabhtaithe",
"Default": "Réamhshocrú", "Default": "Réamhshocrú",
"Default Configuration": "Cumraíocht Réamhshocraithe", "Default Configuration": "Cumraíocht Réamhshocraithe",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Teorainn Ráta Isteach (KiB/s)", "Incoming Rate Limit (KiB/s)": "Teorainn Ráta Isteach (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "D'fhéadfadh cumraíocht mhícheart dochar a dhéanamh d'inneachar d'fhillteáin agus sioncronú a dhéanamh do-oibrithe.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "D'fhéadfadh cumraíocht mhícheart dochar a dhéanamh d'inneachar d'fhillteáin agus sioncronú a dhéanamh do-oibrithe.",
"Incorrect user name or password.": "Ainm úsáideora nó pasfhocal mícheart.", "Incorrect user name or password.": "Ainm úsáideora nó pasfhocal mícheart.",
"Info": "Eolas",
"Internally used paths:": "Cosáin a úsáidtear go hinmheánach:", "Internally used paths:": "Cosáin a úsáidtear go hinmheánach:",
"Introduced By": "Tugtha isteach ag", "Introduced By": "Tugtha isteach ag",
"Introducer": "Réamhrá", "Introducer": "Réamhrá",
@@ -229,7 +227,6 @@
"Learn more": "Faigh tuilleadh eolais", "Learn more": "Faigh tuilleadh eolais",
"Learn more at {%url%}": "Tuilleadh eolais ag {{url}}", "Learn more at {%url%}": "Tuilleadh eolais ag {{url}}",
"Limit": "Teorainn", "Limit": "Teorainn",
"Limit Bandwidth in LAN": "Teorainn a chur ar an bandaleithead i LAN",
"Listener Failures": "Teipeanna an Éisteora", "Listener Failures": "Teipeanna an Éisteora",
"Listener Status": "Stádas an éisteora", "Listener Status": "Stádas an éisteora",
"Listeners": "Éisteoirí", "Listeners": "Éisteoirí",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Taispeáin diff leis an leagan roimhe seo", "Show diff with previous version": "Taispeáin diff leis an leagan roimhe seo",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Taispeántar é in ionad ID gléis i stádas na braisle. Fógrófar é do ghléasanna eile mar ainm réamhshocraithe roghnach.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Taispeántar é in ionad ID gléis i stádas na braisle. Fógrófar é do ghléasanna eile mar ainm réamhshocraithe roghnach.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Taispeántar é in ionad ID gléis i stádas na braisle. Déanfar é a nuashonrú go dtí an t-ainm a fhógraíonn an gléas má fhágtar folamh é.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Taispeántar é in ionad ID gléis i stádas na braisle. Déanfar é a nuashonrú go dtí an t-ainm a fhógraíonn an gléas má fhágtar folamh é.",
"Shut Down": "Múchadh", "Shutdown": "Múchadh",
"Shutdown Complete": "Múchadh Críochnaithe", "Shutdown Complete": "Múchadh Críochnaithe",
"Simple": "Simplí", "Simple": "Simplí",
"Simple File Versioning": "Leagan Simplí Comhad", "Simple File Versioning": "Leagan Simplí Comhad",
+1 -1
View File
@@ -323,7 +323,7 @@
"Show diff with previous version": "Mostrar a diferencia coa versión anterior", "Show diff with previous version": "Mostrar a diferencia coa versión anterior",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrado en lugar do ID de Dispositivo no estado do clúster. Anunciarase a outros dispositivos como nome por defecto opcional.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrado en lugar do ID de Dispositivo no estado do clúster. Anunciarase a outros dispositivos como nome por defecto opcional.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrado en lugar do ID de Dispositivo no estado do clúster. Actualizarase ao nome que anuncia o dispositivo de se deixar baleiro.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrado en lugar do ID de Dispositivo no estado do clúster. Actualizarase ao nome que anuncia o dispositivo de se deixar baleiro.",
"Shut Down": "Apagar", "Shutdown": "Apagar",
"Shutdown Complete": "Apagado Completado", "Shutdown Complete": "Apagado Completado",
"Simple": "Simple", "Simple": "Simple",
"Simple File Versioning": "Versionado de Ficheiros Sinxelo", "Simple File Versioning": "Versionado de Ficheiros Sinxelo",
+1 -4
View File
@@ -27,7 +27,6 @@
"Allowed Networks": "רשתות מורשות", "Allowed Networks": "רשתות מורשות",
"Alphabetic": "אלפביתי", "Alphabetic": "אלפביתי",
"Altered by ignoring deletes.": "השתנה על ידי התעלמות ממחיקות.", "Altered by ignoring deletes.": "השתנה על ידי התעלמות ממחיקות.",
"Always turned on when the folder type is \"{%foldertype%}\".": "תמיד מופעל כאשר סוג התיקייה הוא \"{{foldertype}}\".",
"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.": "פקודה חיצונית מטפלת בניהול הגרסאות. היא חייבת להסיר את הקובץ מהתיקייה המשותפת. אם הנתיב ליישום מכיל רווחים, יש לצטט אותו.", "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 Reporting": "דיווח שימוש אנונימי",
"Anonymous usage report format has changed. Would you like to move to the new format?": "פורמט דוח שימוש אנונימי השתנה. האם ברצונך לעבור לפורמט החדש?", "Anonymous usage report format has changed. Would you like to move to the new format?": "פורמט דוח שימוש אנונימי השתנה. האם ברצונך לעבור לפורמט החדש?",
@@ -53,7 +52,6 @@
"Body:": "גוף:", "Body:": "גוף:",
"Bugs": "באגים", "Bugs": "באגים",
"Cancel": "ביטול", "Cancel": "ביטול",
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "לא ניתן לאפשור כאשר סוג התיקייה הוא \"{{foldertype}}\".",
"Changelog": "יומן שינויים", "Changelog": "יומן שינויים",
"Clean out after": "נקה לאחר", "Clean out after": "נקה לאחר",
"Cleaning Versions": "מנקה גרסאות", "Cleaning Versions": "מנקה גרסאות",
@@ -227,7 +225,6 @@
"Learn more": "למד עוד", "Learn more": "למד עוד",
"Learn more at {%url%}": "למד עוד באתר {{url}}", "Learn more at {%url%}": "למד עוד באתר {{url}}",
"Limit": "מגבלה", "Limit": "מגבלה",
"Limit Bandwidth in LAN": "הגבלת רוחב פס ברשת תקשורת מקומית (LAN)",
"Listener Failures": "כשלי מאזין", "Listener Failures": "כשלי מאזין",
"Listener Status": "מצב מאזין", "Listener Status": "מצב מאזין",
"Listeners": "מאזינים", "Listeners": "מאזינים",
@@ -371,7 +368,7 @@
"Show diff with previous version": "הצג הבדל עם הגרסה הקודמת", "Show diff with previous version": "הצג הבדל עם הגרסה הקודמת",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "מוצג במקום מזהה ההתקן במצב האשכול. יפורסם להתקנים אחרים כשם ברירת מחדל אופציונלי.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "מוצג במקום מזהה ההתקן במצב האשכול. יפורסם להתקנים אחרים כשם ברירת מחדל אופציונלי.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "מוצג במקום מזהה ההתקן במצב האשכול. יעודכן לשם שההתקן מפרסם אם נותר ריק.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "מוצג במקום מזהה ההתקן במצב האשכול. יעודכן לשם שההתקן מפרסם אם נותר ריק.",
"Shut Down": "כיבוי", "Shutdown": "כיבוי",
"Shutdown Complete": "הכיבוי הושלם", "Shutdown Complete": "הכיבוי הושלם",
"Simple": "פשוט", "Simple": "פשוט",
"Simple File Versioning": "ניהול גרסאות קבצים פשוט", "Simple File Versioning": "ניהול גרסאות קבצים פשוט",
+1 -1
View File
@@ -368,7 +368,7 @@
"Show diff with previous version": "पिछले संस्करण के साथ अंतर दिखाएं", "Show diff with previous version": "पिछले संस्करण के साथ अंतर दिखाएं",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "समूह स्थिति में उपकरण ID के बजाय दिखाया गया। वैकल्पिक तयशुदा नाम के रूप में अन्य उपकरणों पर विज्ञापित किया जाएगा।", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "समूह स्थिति में उपकरण ID के बजाय दिखाया गया। वैकल्पिक तयशुदा नाम के रूप में अन्य उपकरणों पर विज्ञापित किया जाएगा।",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "समूह स्थिति में उपकरण ID के बजाय दिखाया गया। खाली छोड़े जाने पर उपकरण द्वारा विज्ञापित नाम में अद्यतित कर दिया जाएगा।", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "समूह स्थिति में उपकरण ID के बजाय दिखाया गया। खाली छोड़े जाने पर उपकरण द्वारा विज्ञापित नाम में अद्यतित कर दिया जाएगा।",
"Shut Down": "शटडाउन", "Shutdown": "शटडाउन",
"Shutdown Complete": "शटडाउन पूर्ण", "Shutdown Complete": "शटडाउन पूर्ण",
"Simple": "सरल", "Simple": "सरल",
"Simple File Versioning": "सरल फाइल संस्करण", "Simple File Versioning": "सरल फाइल संस्करण",
+1 -534
View File
@@ -1,7 +1,4 @@
{ {
"A device with that ID is already added.": "Uređaj s tim ID-om je već dodan.",
"A negative number of days doesn't make sense.": "Negativan broj dana nema smisla.",
"A new major version may not be compatible with previous versions.": "Nova glavna verzija možda neće biti kompatibilna s prethodnim verzijama.",
"API Key": "API ključ", "API Key": "API ključ",
"About": "Informacije", "About": "Informacije",
"Action": "Radnja", "Action": "Radnja",
@@ -11,545 +8,15 @@
"Add Device": "Dodaj uređaj", "Add Device": "Dodaj uređaj",
"Add Folder": "Dodaj mapu", "Add Folder": "Dodaj mapu",
"Add Remote Device": "Dodaj udaljeni uređaj", "Add Remote Device": "Dodaj udaljeni uređaj",
"Add filter entry": "Dodaj unos filtra",
"Add ignore patterns": "Dodaj uzorke zanemarivanja",
"Add new folder?": "Dodati novu mapu?", "Add new folder?": "Dodati novu mapu?",
"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.": "Osim toga, interval ponovnog skeniranja će se povećati (60 puta, tj. nova zadana vrijednost je 1 sat). Također ga možete ručno konfigurirati za svaku mapu kasnije nakon što odaberete „Ne”.",
"Address": "Adresa", "Address": "Adresa",
"Addresses": "Adrese", "Addresses": "Adrese",
"Advanced": "Napredno", "Advanced": "Napredno",
"Advanced Configuration": "Napredna konfiguracija", "Advanced Configuration": "Napredna konfiguracija",
"All Data": "Svi podaci", "All Data": "Svi podaci",
"All Time": "Svo vrijeme", "All Time": "Svo vrijeme",
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Sve mape kaoje se dijele s ovim uređajem moraju biti zaštićene lozinkom, tako da su svi poslani podaci nečitljivi bez navedene lozinke.",
"Allow Anonymous Usage Reporting?": "Dozvoliti anonimno izvještavanje o korištenju?",
"Allowed Networks": "Dozvoljene mreže", "Allowed Networks": "Dozvoljene mreže",
"Alphabetic": "Abecednim redom", "Alphabetic": "Abecednim redom",
"Altered by ignoring deletes.": "Promijenjeno ignoriranjem brisanja.",
"Always turned on when the folder type is \"{%foldertype%}\".": "Uvijek je uključeno kada je vrsta mape „{{foldertype}}“.",
"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.": "Eksterna naredba barata upravljanjem verzijama. Mora ukloniti datoteku iz dijeljene mape. Ako staza do programa sadrži razmake, treba je staviti u navodnike.",
"Anonymous Usage Reporting": "Anonimno izvještavanje o korištenju",
"Anonymous usage report format has changed. Would you like to move to the new format?": "Promijenjen je format za anonimno izvještavanje o korištenju. Želiš li prijeći na novi format?",
"Applied to LAN": "Primijenjeno na LAN",
"Apply": "Primijeni", "Apply": "Primijeni",
"Are you sure you want to override all remote changes?": "Stvarno želite prepisati sve udaljene promjene?", "LDAP": "LDAP"
"Are you sure you want to permanently delete all these files?": "Stvarno želite trajno izbrisati sve ove datoteke?",
"Are you sure you want to remove device {%name%}?": "Stvarno želite ukloniti uređaj {{name}}?",
"Are you sure you want to remove folder {%label%}?": "Stvarno želite ukloniti mapu {{label}}?",
"Are you sure you want to restore {%count%} files?": "Stvarno želite obnoviti {{count}} datoteke(a)?",
"Are you sure you want to revert all local changes?": "Stvarno želite poništiti sve lokalne promjene?",
"Are you sure you want to upgrade?": "Stvarno želite nadograditi?",
"Authentication Required": "Potrebna je autentifikacija",
"Authors": "Autori",
"Auto Accept": "Automatski prihvati",
"Automatic Crash Reporting": "Automatsko izvještavanje o prekidu rada programa",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatska nadogradnja sada nudi izbor između stabilnih izdanja i kandidata za izdanje.",
"Automatic upgrades": "Automatske nadogradnje",
"Automatic upgrades are always enabled for candidate releases.": "Automatske nadogradnje su uvijek uključene za izdanja kandidata.",
"Automatically create or share folders that this device advertises at the default path.": "Automatski stvorite ili dijelite mape koje ovaj uređaj oglašava na zadanoj stazi.",
"Available debug logging facilities:": "Dostupni alati za bilježenje grešaka:",
"Be careful!": "Pazi!",
"Body:": "Sadržaj:",
"Bugs": "Greške",
"Cancel": "Odustani",
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "Ne može se uključiti kada je vrsta mape „{{foldertype}}“.",
"Changelog": "Dnevnik promjena",
"Clean out after": "Očisti nakon",
"Cleaning Versions": "Čišćenje verzija",
"Cleanup Interval": "Interval čišćenja",
"Click to see full identification string and QR code.": "Kliknite za prikaz potpunog identifikacijskog niza i QR koda.",
"Close": "Zatvori",
"Command": "Naredba",
"Comment, when used at the start of a line": "Komentar, kada se koristi na početku retka",
"Compression": "Kompresija",
"Configuration Directory": "Direktorij konfiguracije",
"Configuration File": "Datoteka konfiguracije",
"Configured": "Konfigurirano",
"Connected (Unused)": "Povezano (nekorišteno)",
"Connection Error": "Greška u vezi",
"Connection Management": "Upravljanje vezama",
"Connection Type": "Vrsta veze",
"Connections": "Veze",
"Connections via relays might be rate limited by the relay": "Veze putem releja mogu biti ograničene brzinom releja",
"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.": "Kontinuirano praćenje promjena sada je dostupno unutar Syncthinga. Ovo će otkriti promjene na disku i pokrenuti skeniranje samo promijenjenih staza. Prednosti su da se promjene brže šire i da je potreban manji broj potpunih skeniranja.",
"Copied from elsewhere": "Kopirano iz jednog drugog mjesta",
"Copied from original": "Kopirano iz originala",
"Copied!": "Kopirano!",
"Copy": "Kopiraj",
"Copy failed! Try to select and copy manually.": "Kopiranje nije uspjelo! Pokušajte ručno odabrati i kopirati.",
"Currently Shared With Devices": "Trenutačno se dijeli s uređajima",
"Custom Range": "Prilagođeni raspon",
"Danger!": "Opasnost!",
"Database Location": "Lokacija baze podataka",
"Debug": "Otklanjanje grešaka",
"Debugging Facilities": "Alati za otklanjanje grešaka",
"Default": "Zadano",
"Default Configuration": "Zadana konfiguracija",
"Default Device": "Zadani uređaj",
"Default Folder": "Zadana mapa",
"Default Ignore Patterns": "Zadani uzorci zanemarivanja",
"Defaults": "Zadane vrijednosti",
"Delete": "Izbriži",
"Delete Unexpected Items": "Izbriši neočekivane stavke",
"Deleted {%file%}": "Izbrisano {{file}}",
"Deselect All": "Odznači sve",
"Deselect devices to stop sharing this folder with.": "Odznačite uređaje da biste prestali dijeliti ovu mapu s njima.",
"Deselect folders to stop sharing with this device.": "Odznačite mape da biste ih prestali dijeliti s ovim uređajem.",
"Device": "Uređaj",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Uređaj „{{name}}“ ({{device}} na {{address}}) se želi povezati. Dodati novi uređaj?",
"Device Certificate": "Certifikat uređaja",
"Device ID": "ID uređaja",
"Device Identification": "Identifikacija uređaja",
"Device Name": "Ime uređaja",
"Device Status": "Stanje uređaja",
"Device is untrusted, enter encryption password": "Uređaj je nepovjerljiv, unesite lozinku za šifriranje",
"Device rate limits": "Ograničenja brzine uređaja",
"Device that last modified the item": "Uređaj koji je zadnji put promijenio stavku",
"Devices": "Uređaji",
"Disable Crash Reporting": "Isključi izvještavanje o prekidu rada programa",
"Disabled": "Isključeno",
"Disabled periodic scanning and disabled watching for changes": "Isključeno periodično skeniranje i isključeno praćenje promjena",
"Disabled periodic scanning and enabled watching for changes": "Isključeno periodično skeniranje i uključeno praćenje promjena",
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Isključeno periodično skeniranje i neuspjelo postavljanje praćenja promjena, ponovni pokušaj svake 1 min:",
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Isključuje uspoređivanje i sinkroniziranje dozvola za datoteke. Korisno na sustavima s nepostojećim ili prilagođenim dozvolama (npr. FAT, exFAT, Synology, Android).",
"Discard": "Odbaci",
"Disconnected": "Odspojeno",
"Disconnected (Inactive)": "Odspojeno (neaktivno)",
"Disconnected (Unused)": "Odspojeno (neiskorišteno)",
"Discovered": "Otkriveno",
"Discovery": "Otkrivanje",
"Discovery Failures": "Neuspjella otkrivanja",
"Discovery Status": "Stanje otkrivanja",
"Dismiss": "Odbaci",
"Do not add it to the ignore list, so this notification may recur.": "Nemojte je dodati na popis za zanemarivanje, kako bi se ova obavijest mogla ponovo pojaviti.",
"Do not restore": "Nemoj obnoviti",
"Do not restore all": "Nemoj sve obnoviti",
"Do you want to enable watching for changes for all your folders?": "Želite li uključiti praćenje promjena za sve svoje mape?",
"Documentation": "Dokumentacija",
"Download Rate": "Stopa preuzimanja",
"Downloaded": "Preuzeto",
"Downloading": "Preuzimanje",
"Edit": "Uredi",
"Edit Device": "Uredi uređaj",
"Edit Device Defaults": "Uredi zadane postavke uređaja",
"Edit Folder": "Uredi mapu",
"Edit Folder Defaults": "Uredi zadane postavke mape",
"Editing {%path%}.": "Uređivanje {{path}}.",
"Enable Crash Reporting": "Uključi izvještavanje o prekidu rada programa",
"Enable NAT traversal": "Uključi NAT povezivanje",
"Enable Relaying": "Uključi komunikaciju putem releja",
"Enabled": "Uključeno",
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Uključuje slanje proširenih svojstva na druge uređaje i primjenu dolaznih proširenih svojstva. Može zahtijevati pokretanje s povlaštenim privilegijama.",
"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.": "Uključuje slanje proširenih svojstva drugim uređajima, ali ne primijenjuje dolazna proširena svojstva. To može imati značajan utjecaj na performansu. Uvijek je uključeno kada je uključena opcija „Sinkroniziraj proširena svojstva”.",
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Uključuje slanje podataka o vlasništvu na druge uređaje i primjenu dolaznih podataka o vlasništvu. Obično zahtijeva pokretanje s povlaštnim privilegijama.",
"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.": "Uključuje slanje podataka vlasništva drugim uređajima, ali ne primijenjuje dolazne podatke vlasništva. To može imati značajan utjecaj na performansu. Uvijek je uključeno kada je uključena opcija „Sinkroniziraj vlasništvo”.",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Unesite nenegativan broj (npr. „2,35“) i odaberite jedinicu. Postoci su dio ukupne veličine diska.",
"Enter a non-privileged port number (1024 - 65535).": "Unesite broj neprivilegiranog priključka (1024 do 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Unesite adrese odvojene zarezom („tcp://ip:port“, „tcp://host:port“) ili „dinamičko“ za izvršavanje automatskog otkrivanja adrese.",
"Enter ignore patterns, one per line.": "Unesite uzorke zanemarivanja, jedan po retku.",
"Enter up to three octal digits.": "Unesite do tri oktalne znamenke.",
"Error": "Greška",
"Extended Attributes": "Proširena svojstva",
"Extended Attributes Filter": "Filtar proširenih svojstva",
"External": "Eksterno",
"External File Versioning": "Eksterno upravljanje verzijama datoteka",
"Failed Items": "Neuspjele stavke",
"Failed to load file versions.": "Učitavanje verzija datoteke nije uspjelo.",
"Failed to load ignore patterns.": "Učitavanje uzoraka za zanemarivanje nije uspjelo.",
"Failed to set up, retrying": "Postavljanje nije uspjelo, ponovni pokušaj",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Neuspjelo povezivanje s IPv6 serverima je normalno ako ne postoji IPv6 veza.",
"File Pull Order": "Redoslijed preuzimanja datoteka",
"File Versioning": "Upravljanje verzijama datoteka",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Datoteke se premještaju u .stversions direktorij kada ih Syncthing zamijeni ili izbriše.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Datoteke se premještaju u verzije s datumom u .stversions direktorij kada ih Syncthing zamijeni ili izbriše.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Datoteke su zaštićene od promjena na drugim uređajima, ali promjene koje su napravljene na ovom uređaju će se poslati ostatku klastera.",
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Datoteke se sinkroniziraju iz klastera, ali sve lokalno napravljene promjene se neće slati na druge uređaje.",
"Filesystem Watcher Errors": "Greške u praćenju datotečnog sustava",
"Filter by date": "Filtriraj po datumu",
"Filter by name": "Filtriraj po imenu",
"Folder": "Mapa",
"Folder ID": "ID mape",
"Folder Label": "Oznaka mape",
"Folder Path": "Staza mape",
"Folder Status": "Stanje mape",
"Folder Type": "Vrsta mape",
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Vrsta mape „{{receiveEncrypted}}“ se može postaviti samo prilikom dodavanja nove mape.",
"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.": "Vrsta mape „{{receiveEncrypted}}“ se ne može promijeniti nakon dodavanja mape. Morate ukloniti mapu, izbrisati ili dešifrirati podatke na disku i mapu ponovo dodati.",
"Folders": "Mape",
"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.": "Dogodila se greška u sljedećim mapama prilikom početka praćenja promjena. Pokušat će se ponavljati svake minute, tako da bi greške uskoro mogle nestati. Ako ne nestanu, pokušajte riješiti temeljni problem i zatražite pomoć ako ga ne možete riješiti.",
"Forever": "Zauvijek",
"Full Rescan Interval (s)": "Interval potpunog ponovnog skeniranja (s)",
"GUI": "Grafičko korisničko sučelje",
"GUI / API HTTPS Certificate": "HTTPS certifikat za GUI / API",
"GUI Authentication Password": "Lozinka za GUI autentifikacju",
"GUI Authentication User": "Korisnik za GUI autentifikacju",
"GUI Authentication: Set User and Password": "GUI autentifikacija: Postavite korisnika i lozinku",
"GUI Override Directory": "Direktorij za nadjačavanje GUI-ja",
"GUI Theme": "Tema GUI-ja",
"General": "Općenito",
"Generate": "Generiraj",
"Global Discovery": "Globalno otkrivanje",
"Global Discovery Servers": "Serveri za globalno otkrivanje",
"Global State": "Globalno stanje",
"Help": "Pomoć",
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Savjet: otkriveno je samo odbij-pravila dok je zadana postavka „Odbij“. Razmislite o dodavanju „dozvoli bilo koje“ kao posljednje pravilo.",
"Home page": "Početna stranica",
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Međutim, vaše trenutačne postavke ukazuju da možda ne želite da je uključeno. Za vas smo isključili automatsko izvještavanje o pregidu rada programa.",
"Identification": "Identifikacija",
"If untrusted, enter encryption password": "Ako je nepovjerljiv, unesite lozinku za šifriranje",
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Ako želite spriječiti druge korisnike na ovom računalu da pristupe Syncthingu i putem njega vašim datotekama, razmislite o postavljanju autentifikacije.",
"Ignore": "Zanemari",
"Ignore Patterns": "Uzorci zanemarivanja",
"Ignore Permissions": "Zanemari dozvole",
"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.": "Uzorci zanemarivanja mogu se dodati tek nakon što se mapa stvori. Ako je označeno, nakon spremanja će se prikazati polje za unos uzoraka zanemarivanja.",
"Ignored Devices": "Zanemareni uređaji",
"Ignored Folders": "Zanemarene mape",
"Ignored at": "Zanemaren na",
"Included Software": "Uključeni softver",
"Incoming Rate Limit (KiB/s)": "Dolazno ograničenje brzine (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Neispravna konfiguracija može oštetiti sadržaj vaše mape kao i ispravno funkcioniranje Syncthinga.",
"Incorrect user name or password.": "Neispravno korisničko ime ili lozinka.",
"Info": "Informacije",
"Internally used paths:": "Interno korištene staze:",
"Introduction": "Uvod",
"Inversion of the given condition (i.e. do not exclude)": "Inverzija zadanog uvjeta (tj. ne isključuj)",
"Keep Versions": "Zadrži verzije",
"LDAP": "LDAP",
"Largest First": "Najprije najveće",
"Last 30 Days": "Zadnjih 30 dana",
"Last 7 Days": "Zadnjih 7 dana",
"Last Month": "Prošli mjesec",
"Last Scan": "Zadnje skeniranje",
"Last seen": "Zadnje viđeno",
"Latest Change": "Zadnja promjena",
"Learn more": "Saznaj više",
"Learn more at {%url%}": "Saznaj više na {{url}}",
"Limit": "Ograničenje",
"Limit Bandwidth in LAN": "Ograniči propusnost u LAN-u",
"Listener Failures": "Neuspjesi slušača",
"Listener Status": "Stanje slušača",
"Listeners": "Slušači",
"Loading data...": "Učitavanje podataka …",
"Loading...": "Učitavanje …",
"Local Additions": "Lokalni dodaci",
"Local Discovery": "Lokalno otkrivanje",
"Local State": "Lokalno stanje",
"Local State (Total)": "Lokalno stanje (ukupno)",
"Locally Changed Items": "Lokalno promijenjene stavke",
"Log": "Zapis",
"Log File": "Datoteka zapisa",
"Log In": "Prijavi se",
"Log Out": "Odjavi se",
"Log in to see paths information.": "Prijavite se da biste vidjeli informacije o stazama.",
"Log in to see version information.": "Prijavite se da biste vidjeli informacije o verziji.",
"Log tailing paused. Scroll to the bottom to continue.": "Praćenje zapisa je pauzirano. Pomaknite se na dno kako biste nastavili.",
"Login failed, see Syncthing logs for details.": "Prijava nije uspjela. Pogledaj detalje u odjeljku zapisima sinkronizacije.",
"Logs": "Zapisi",
"Major Upgrade": "Velika nadogradnja",
"Mass actions": "Masovne radnje",
"Maximum Age": "Maksimalna starost",
"Maximum single entry size": "Maksimalna veličina pojedinačnog unosa",
"Maximum total size": "Maksimalna ukupna veličina",
"Metadata Only": "Samo metapodaci",
"Minimum Free Disk Space": "Minimalna količina slobodnog prostora na disku",
"Mod. Device": "Uređaj promjene",
"Mod. Time": "Vrijeme promjene",
"More than a month ago": "Prije više od mjesec dana",
"More than a week ago": "Prije više od tjedan dana",
"More than a year ago": "Prije više od godinu dana",
"Move to top of queue": "Premjesti na vrh popisa",
"Multi level wildcard (matches multiple directory levels)": "Višerazinski zamjenski znak (podudara se s više razina direktorija)",
"Never": "Nikada",
"New Device": "Novi uređaj",
"New Folder": "Nova mapa",
"Newest First": "Najprije najnovije",
"No": "Ne",
"No File Versioning": "Bez upravljanje verzijama datoteka",
"No files will be deleted as a result of this operation.": "Nijedna datoteka se neće izbrisati kao rezultat ove operacije.",
"No rules set": "Nema postavljenih pravila",
"No upgrades": "Nema nadogradnji",
"Not shared": "Ne dijeli se",
"Notice": "Napomena",
"Number of Connections": "Broj veza",
"OK": "U redu",
"Off": "Isključeno",
"Oldest First": "Najprije najstarije",
"Optional descriptive label for the folder. Can be different on each device.": "Neobavezna opisna etiketa za mapu. Može biti različita na svakom uređaju.",
"Options": "Opcije",
"Out of Sync": "Nesinkronizirano",
"Out of Sync Items": "Nesinkronizirane stavke",
"Outgoing Rate Limit (KiB/s)": "Odlazno ograničenje brzine (KiB/s)",
"Override": "Nadjačavanje",
"Override Changes": "Nadjačaj promjene",
"Ownership": "Vlasništvo",
"Password": "Lozinka",
"Path": "Staza",
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Staza do mape na lokalnom računalu. Stvorit će se ako ne postoji. Znak tildе (~) može se koristiti kao prečac za",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Staza gdje bi se verzije trebale spremati (ostavite prazno za zadani direktorij .stversions u dijeljenoj mapi).",
"Paths": "Staze",
"Pause": "Pauziraj",
"Pause All": "Pauziraj sve",
"Paused": "Pauzirano",
"Paused (Unused)": "Pauzirano (neiskorišteno)",
"Pending changes": "Promjene na čekanju",
"Periodic scanning at given interval and disabled watching for changes": "Periodično skeniranje u zadanom intervalu i iskljjučeo praćenje promjena",
"Periodic scanning at given interval and enabled watching for changes": "Periodično skeniranje u zadanom intervalu i uključeno praćenje promjena",
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodično skeniranje u zadanom intervalu i neuspjelo postavljanje praćenja promjena, ponavlja se svake 1 min:",
"Permanently add it to the ignore list, suppressing further notifications.": "Stalno dodajte na popis zanemarivanja, potiskujući daljnje obavijesti.",
"Please consult the release notes before performing a major upgrade.": "Pročitajta bilješke o izdanju prije izvršavanja velike nadogradnje.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Postavite korisnika i lozinku za GUI autentifikaciju u dijalogu Postavke.",
"Please wait": "Pričekajte",
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefiks koji označava da se datoteka može izbrisati ako sprečava uklanjanje direktorija",
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefiks koji označava da se uzorak treba usporediti bez razlikovanja velikih i malih slova",
"Preparing to Sync": "Priprema za sinkronizaciju",
"Preview": "Pregled",
"Preview Usage Report": "Pregled izvještaja o korištenju",
"QR code": "QR kod",
"QUIC LAN": "QUIC LAN",
"QUIC WAN": "QUIC WAN",
"Quick guide to supported patterns": "Kratki vodič za podržane uzorke",
"Random": "Slučajno",
"Receive Encrypted": "Primi šifrirano",
"Receive Only": "Samo primaj",
"Received data is already encrypted": "Primljeni podaci su već šifrirani",
"Recent Changes": "Nedavne promjene",
"Reduced by ignore patterns": "Reducirano pomoću uzoraka zanemarivanja",
"Relay LAN": "LAN relej",
"Relay WAN": "WAN relej",
"Release Notes": "Bilješke o izdanju",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Kandidati za izdanje sadrže najnovije funkcije i ispravke. Slični su tradicionalnim dvotjednim izdanjima Syncthinga.",
"Remote Devices": "Udaljeni uređaji",
"Remote GUI": "Udaljeni GUI",
"Remove": "Ukloni",
"Remove Device": "Ukloni uređaj",
"Remove Folder": "Ukloni mapu",
"Required identifier for the folder. Must be the same on all cluster devices.": "Obavezni identifikator za mapu. Mora biti isti na svim uređajima u klasteru.",
"Rescan": "Ponovo skeniraj",
"Rescan All": "Ponovo skeniraj sve",
"Rescans": "Ponovna skeniranja",
"Restart": "Pokreni ponovo",
"Restart Needed": "Potrebno je ponovno pokretanje",
"Restarting": "Ponovno pokretanje",
"Restore": "Obnovi",
"Restore Versions": "Obnovi verzije",
"Resume": "Nastavi",
"Resume All": "Nastavi sve",
"Reused": "Ponovo koršteno",
"Revert": "Poništi",
"Revert Local Changes": "Poništi lokalne promjene",
"Save": "Spremi",
"Saving changes": "Spremanje promjena",
"Scan Time Remaining": "Preostalo vrijeme skeniranja",
"Scanning": "Skeniranje",
"See external versioning help for supported templated command line parameters.": "Pogledajte pomoć za upravljanje verzijama eksternih datoteka za podržane parametre naredbenog retka u stilu predložaka.",
"Select All": "Odaberi sve",
"Select a version": "Odaberi verziju",
"Select additional devices to share this folder with.": "Odaberite dodatne uređaje za dijeljenje s ovom mapom.",
"Select additional folders to share with this device.": "Odaberite dodatne mape za dijeljenje s ovim uređajem.",
"Select latest version": "Odaberi najnoviju verziju",
"Select oldest version": "Odaberi najstariju verziju",
"Send & Receive": "Šalji i primaj",
"Send Extended Attributes": "Šalji proširena svojstva",
"Send Only": "Samo šalji",
"Send Ownership": "Šalji vlasništvo",
"Set Ignores on Added Folder": "Postavi zanemarivanja na dodanu mapu",
"Settings": "Postavke",
"Share": "Dijeli",
"Share Folder": "Dijeli mapu",
"Share by Email": "Dijeli putem e-pošte",
"Share by SMS": "Dijeli putem SMS-a",
"Share this folder?": "Dijeliti ovu mapu?",
"Shared Folders": "Dijeljenje mape",
"Shared With": "Dijeli se sa",
"Sharing": "Dijeljenje",
"Show ID": "Prikaži ID",
"Show QR": "Prikaži QR",
"Show detailed discovery status": "Prikaži detaljno stanje otkrivanja",
"Show detailed listener status": "Prikaži detaljno stanje slušača",
"Show diff with previous version": "Prikaži razliku s prethodnom verzijom",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Prikazuje se umjesto ID-ja uređaja u stanju klastera. Bit će predstavljeno drugim uređajima kao opcionalno zadano ime.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Prikazuje se umjesto ID-ja uređaja u stanju klastera. Bit će aktualizirano na ime koje uređaj predstavlja ako se ostavi przno.",
"Shut Down": "Isključi",
"Shutdown Complete": "Isključivanje dovršeno",
"Simple": "Jednostavno",
"Simple File Versioning": "Jednostavno upravljanje verzijama datoteka",
"Single level wildcard (matches within a directory only)": "Jednorazinski zamjenski znak (podudara se samo unutar direktorija)",
"Size": "Veličina",
"Smallest First": "Najprije najmanje",
"Some discovery methods could not be established for finding other devices or announcing this device:": "Neke metode otkrivanja se nisu mogle uspostaviti za pronalaženje drugih uređaja ili najavljivanje ovog uređaja:",
"Some items could not be restored:": "Neke se stavke nisu mogle obnoviti:",
"Some listening addresses could not be enabled to accept connections:": "Neke adrese za osluškivanje se nisu mogle uključiti za prihvaćanje veza:",
"Source Code": "Izvorni kod",
"Stable releases and release candidates": "Stabilna izdanja i kandidati za izdanje",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stabilna izdanja kasne oko dva tjedna. Tijekom tog vremena se testiraju kao kandidati za izdanje.",
"Stable releases only": "Samo stabilna izdanja",
"Staggered": "U fazama",
"Staggered File Versioning": "Upravljanje verzijama datoteka u fazama",
"Start Browser": "Pokreni preglednik",
"Statistics": "Statistike",
"Stay logged in": "Ostanite prijavljeni",
"Stopped": "Zaustavljeno",
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Sprema i sinkronizira samo šifrirane podatke. Mape na svim povezanim uređajima moraju biti postavljene s istom lozinkom ili također biti vrste „{{receiveEncrypted}}“.",
"Subject:": "Predmet:",
"Support": "Podrška",
"Support Bundle": "Paket podrške",
"Sync Extended Attributes": "Sinkroniziraj proširena svojstva",
"Sync Ownership": "Sinkroniziraj vlasništvo",
"Sync Status": "Stanje sinkronizacije",
"Syncing": "Sinkroniziranje",
"Syncthing device ID for \"{%devicename%}\"": "Syncthing ID uređaja za „{{devicename}}“",
"Syncthing has been shut down.": "Syncthing je isključen.",
"Syncthing includes the following software or portions thereof:": "Syncthing uključuje sljedeći softver ili njegove dijelove:",
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing je besplatan softver otvorenog koda s licencom 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 je program za kontinuiranu sinkronizaciju datoteka. Sinkronizira datoteke između dva ili više računala u stvarnom vremenu, sigurno zaštićene od znatiželjnih očiju. Vaši podaci su isključivo vaši i mođete odlučiti gdje će se spremati, hoće li se dijeliti s nekim trećim stranama i kako će se prenositi preko interneta.",
"Syncthing is listening on the following network addresses for connection attempts from other devices:": "Syncthing osluškuje na sljedećim mrežnim adresama pokušaje povezivanja s drugih uređaja:",
"Syncthing is not listening for connection attempts from other devices on any address. Only outgoing connections from this device may work.": "Syncthing ne prima pokušaje povezivanja s drugih uređaja na bilo kojoj adresi. Moguće je da rade samo odlazne veze s ovog uređaja.",
"Syncthing is restarting.": "Syncthing se ponovo pokreće.",
"Syncthing is saving changes.": "Syncthing sprema promjene.",
"Syncthing is upgrading.": "Syncthing se nadograđuje.",
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing sada podržava automatsko prijavljivanje pregida rada programa programerima. Ova je funkcija standardno uključena.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Čini se da Syncthing ne radi ili postoji problem s internetskom vezom. Pokušaj se ponavlja …",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Čini se da Syncthing ima problem u obradi vašeg zahtjeva. Altualizirajte stranicu ili ponovo pokrenite Syncthing ako problem ne nestane.",
"TCP LAN": "TCP LAN",
"TCP WAN": "TCP WAN",
"Take me back": "Vrati me natrag",
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Opcije pokretanja nadjačavaju GUI adresu. Ovdje učinjene promjene neće stupiti na snagu dok je nadjačavanje postavljeno.",
"The Syncthing Authors": "Syncthing autori",
"The Syncthing admin interface is configured to allow remote access without a password.": "Administratorsko sučelje Syncthinga konfigurirano je tako da dopušta udaljeni pristup bez lozinke.",
"The aggregated statistics are publicly available at the URL below.": "Prikupljeni statistički podaci javno su dostupni na URL-u u nastavku.",
"The cleanup interval cannot be blank.": "Interval čišćenja ne može biti prazan.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfiguracija je spremljena, ali nije aktivirana. Syncthing se mora ponovo pokrenuti kako bi se aktivirala nova konfiguracija.",
"The device ID cannot be blank.": "ID uređaja ne može biti prazan.",
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "ID uređaja koji ovdje treba unijeti se može pronaći u dijalogu „Radnje > Prikaži ID“ na drugom uređaju. Razmaci i crtice su opcionalni (zanemaruju se).",
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Šifrirani izvještaj o korištenju šalje se svakodnevno. Koristi se za praćenje uobičajenih platformi, veličina mapa i verzija programa. Ako se prijavljeni skup podataka promijeni, ovaj će se dijalog ponovo prikazati.",
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Uneseni ID uređaja ne valja. Trebao bi biti niz od 52 ili 56 znakova koji se sastoji od slova i brojeva, s razmacima i opcionalno sa crticama.",
"The folder ID cannot be blank.": "ID mape ne može biti prazan.",
"The folder ID must be unique.": "ID mape mora biti jedinstven.",
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Sadržaj mape na drugim uređajima će se prepisati kako bi postao identičan s ovim uređajem. Datoteke koje nisu ovdje će se izbrisati na drugim uređajima.",
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Sadržaj mape na ovom uređaju će se prepisati kako bi postao identičan s drugim uređajima. Ovdje novo dodane datoteke će se izbrisati.",
"The folder path cannot be blank.": "Staza mape ne može biti prazna.",
"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.": "Koriste se sljedeći intervali: u prvom satu se verzija čuva svakih 30 sekundi, prvi dan se verzija čuva svaki sat, prvih 30 dana se verzija čuva svaki dan, a do maksimalne starosti verzija se čuva svaki tjedan.",
"The following items could not be synchronized.": "Sljedeće stavke se nisu mogle sinkronizirati.",
"The following items were changed locally.": "Sljedeće stavke su promijenjene lokalno.",
"The following methods are used to discover other devices on the network and announce this device to be found by others:": "Sljedeće metode se koriste za otkrivanje drugih uređaja na mreži i objavljivanje ovog uređaja drugima:",
"The following text will automatically be inserted into a new message.": "Sljedeći tekst će se automatski umetnuti u novu poruku.",
"The following unexpected items were found.": "Pronađene su sljedeće neočekivane stavke.",
"The interval must be a positive number of seconds.": "Interval mora biti pozitivan broj sekundi.",
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Interval, u sekundama, za pokretanje čišćenja u direktoriju verzija. Nula za isključivanje periodičnog čišćenja.",
"The maximum age must be a number and cannot be blank.": "Maksimalna starost mora biti broj i ne može biti prazna.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Maksimalno vrijeme za zadržavanje verzije (u danima, postavite na 0 da bi se verzije zauvijek zadržale).",
"The number of connections must be a non-negative number.": "Broj veza mora biti nenegativan broj.",
"The number of days must be a number and cannot be blank.": "Broj dana mora biti broj i ne može biti prazan.",
"The number of days to keep files in the trash can. Zero means forever.": "Broj dana za čuvanje datoteka u kanti za smeće. Nula znači zauvijek.",
"The number of old versions to keep, per file.": "Broj starih verzija koje se trebaju zadržati, po datoteci.",
"The number of versions must be a number and cannot be blank.": "Broj verzija mora biti broj i ne može biti prazan.",
"The path cannot be blank.": "Staza ne može biti prazna.",
"The rate limit is applied to the accumulated traffic of all connections to this device.": "Ograničenje brzine se primjenjuje na ukupni promet svih veza s ovim uređajem.",
"The rate limit must be a non-negative number (0: no limit)": "Ograničenje brzine mora biti nenegativan broj (0: bez ograničenja)",
"The remote device has not accepted sharing this folder.": "Udaljeni uređaj nije prihvatio dijeljenje ove mape.",
"The remote device has paused this folder.": "Udaljeni uređaj je pauzirao ovu mapu.",
"The rescan interval must be a non-negative number of seconds.": "Interval ponovnog skeniranja mora biti nenegativan broj sekundi.",
"There are no devices to share this folder with.": "Nema uređaja za dijeljenje ove mape.",
"There are no file versions to restore.": "Nema verzija datoteke za obnavljanje.",
"There are no folders to share with this device.": "Nema mapa za dijeljenje s ovim uređajem.",
"They are retried automatically and will be synced when the error is resolved.": "Ponovni pokušaji će se izvršiti automatski i sinkronizirat će se kada se greška riješi.",
"This Device": "Ovaj uređaj",
"This Month": "Ovaj mjesec",
"This can easily give hackers access to read and change any files on your computer.": "Ovo hakerima omogućuje jednostavan pristup za čitanje i mijenjanje bilo kojih datoteka na vašem računalu.",
"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.": "Ovaj uređaj ne može automatski otkriti druge uređaje niti objaviti vlastitu adresu kako bi je drugi pronašli. Povezati se mogu samo uređaji sa statički konfiguriranim adresama.",
"This is a major version upgrade.": "Ovo je nadogradnja glavne verzije.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Ova postavka upravlja potrebnom slobodnom memorijom na glavnom disku (tj. disku baze podataka indeksa).",
"Time": "Vrijeme",
"Time the item was last modified": "Vrijeme zadnje promjene stavke",
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "Za povezivanje sa Syncthing uređajem nazvanim „{{devicename}}“, dodajte novi udaljeni uređaj s ovim ID-om na svojoj strani:",
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Za dopuštanje pravila, označite polje. Za odbijanje pravila, ostavite polje neoznačeno.",
"Today": "Danas",
"Trash Can": "Kanta za smeće",
"Trash Can File Versioning": "Upravljanje verzijama datoteka u kanti za smeće",
"Type": "Vrsta",
"UNIX Permissions": "UNIX dozvola",
"Unavailable": "Nedostupno",
"Unavailable/Disabled by administrator or maintainer": "Nedostupno/Onemogućeno od administratora ili održavatelja",
"Undecided (will prompt)": "Neodlučeno (odluka će se zatražiti)",
"Unexpected Items": "Neočekivane stavke",
"Unexpected items have been found in this folder.": "U ovoj su mapi pronađene neočekivane stavke.",
"Unignore": "Poništi zanemarivanje",
"Unknown": "Nepoznato",
"Unshared": "Nedijeljeno",
"Unshared Devices": "Nedijeljeni uređaji",
"Unshared Folders": "Nedijeljene mape",
"Untrusted": "Nepovjerljivo",
"Up to Date": "Aktualno",
"Updated {%file%}": "Aktualizirano {{file}}",
"Upgrade": "Nadogradi",
"Upgrade To {%version%}": "Nadogradi na {{version}}",
"Upgrading": "Nadograđivanje",
"Upload Rate": "Stopa prijenosa",
"Uptime": "Vrijeme rada",
"Usage reporting is always enabled for candidate releases.": "Izvještavanje o korištenju je uvijek uključeno za izdanja kandidata.",
"Use HTTPS for GUI": "Koristi HTTPS za GUI",
"Use notifications from the filesystem to detect changed items.": "Koristite obavijesti iz datotečnog sustava za otkrivanje promijenjenih stavki.",
"User": "Korisnik",
"User Home": "Korisnički direktorij",
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Korisničko ime/lozinka nisu postavljeni za GUI autentifikaciju. Razmislite o njihovom postavljanju.",
"Using a QUIC connection over LAN": "Korištenje QUIC veze preko LAN-a",
"Using a QUIC connection over WAN": "Korištenje QUIC veze preko WAN-a",
"Using a direct TCP connection over LAN": "Korištenje izravne TCP veze preko LAN-a",
"Using a direct TCP connection over WAN": "Korištenje izravne TCP veze preko WAN-a",
"Version": "Verzija",
"Versions": "Verzije",
"Versions Path": "Staza verzija",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Verzije se automatski brišu ako su starije od maksimalne starosti ili premaše broj dopuštenih datoteka u intervalu.",
"Waiting to Clean": "Čekanje na čišćenje",
"Waiting to Scan": "Čekanje na skeniranje",
"Waiting to Sync": "Čekanje na sinkronizaciju",
"Warning": "Upozorenje",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Upozorenje, ova je staza nadređeni direktorij postojeće mape „{{otherFolder}}“.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Upozorenje, ova je staza nadređeni direktorij postojeće mape „{{otherFolderLabel}}“ ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Upozorenje, ova je staza poddirektorij postojeće mape „{{otherFolder}}“.",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Upozorenje, ova je staza poddirektorij postojeće mape „{{otherFolderLabel}}“ ({{otherFolder}}).",
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Upozorenje: Ako koristite eksterni alat za praćenje kao što je {{syncthingInotify}}, osigurajte da jei deaktiviran.",
"Watch for Changes": "Prati promjene",
"Watching for Changes": "Praćenje promjena",
"Watching for changes discovers most changes without periodic scanning.": "Praćenje promjena otkriva većinu promjena bez periodičnog skeniranja.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Prilikom dodavanja novog uređaja imajte na umu da se ovaj uređaj mora dodati i na drugoj strani.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Prilikom dodavanja nove mape imajte na umu da se ID mape koristi za povezivanje mapa između uređaja. Razlikuju velika i mala slova i moraju se točno podudarati između svih uređaja.",
"When set to more than one on both devices, Syncthing will attempt to establish multiple concurrent connections. If the values differ, the highest will be used. Set to zero to let Syncthing decide.": "Kada je postavljen na više od jednog na oba uređaja, Syncthing će pokušati uspostaviti više istodobnih veza. Ako se vrijednosti razlikuju, koristit će se najviša. Postavite na nulu kako bi Syncthing odlučio.",
"Yes": "Da",
"Yesterday": "Jučer",
"You can also copy and paste the text into a new message manually.": "Tekst možete i ručno kopirati i zalijepiti u novu poruku.",
"You can also select one of these nearby devices:": "Možete odabrati i jedan od sljedećih uređaja u blizini:",
"You can change your choice at any time in the Settings dialog.": "Izbor možete promijeniti u bilo kojem trenutku u dijalogu „Postavke“.",
"You can read more about the two release channels at the link below.": "Saznajte više o dvama izdavačkim kanalima putem sljedeće poveznice.",
"You have no ignored devices.": "Nemate zanemarene uređaje.",
"You have no ignored folders.": "Nemate zanemarene mape.",
"You have unsaved changes. Do you really want to discard them?": "Imate nespremljene promjene. Želite li ih doista odbaciti?",
"You must keep at least one version.": "Morate zadržati barem jednu verziju.",
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "Nemojte nikada nešto lokalno dodavati ili mijenjati u mapi „{{receiveEncrypted}}“.",
"Your SMS app should open to let you choose the recipient and send it from your own number.": "Vaša program za SMS bi se trebao otvoriti kako biste mogli odabrati primatelja i poslati poruku sa svog broja.",
"Your email app should open to let you choose the recipient and send it from your own address.": "Vaša program za e-poštu bi se trebao otvoriti kako biste mogli odabrati primatelja i poslati poruku s vlastite adrese.",
"days": "dani",
"deleted": "izbrisano",
"deny": "odbij",
"directories": "direktoriji",
"file": "datoteka",
"files": "datoteke",
"folder": "mapa",
"full documentation": "potpuna dokumentacija",
"items": "stavke",
"modified": "promjenjeno",
"permit": "dozvoli",
"seconds": "sekunde",
"theme": {
"name": {
"black": "Crna",
"dark": "Tamna",
"default": "Zadano",
"light": "Svijetla"
}
},
"unknown device": "nepoznat uređaj",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} želi dijeliti mapu „{{folder}}“.",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} želi dijeliti mapu „{{folderlabel}}“ ({{folder}}).",
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} bi možda mogao ponovno uvesti ovaj uređaj."
} }
+1 -1
View File
@@ -345,7 +345,7 @@
"Show diff with previous version": "Előző verzió eltérésének megjelenítése", "Show diff with previous version": "Előző verzió eltérésének megjelenítése",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Az eszközazonosító helyett jelenik meg. A többi eszközön alapértelmezett névként használható.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Az eszközazonosító helyett jelenik meg. A többi eszközön alapértelmezett névként használható.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Az eszközazonosító helyett jelenik meg. Üresen hagyva az eszköz saját neve lesz alkalmazva.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Az eszközazonosító helyett jelenik meg. Üresen hagyva az eszköz saját neve lesz alkalmazva.",
"Shut Down": "Leállítás", "Shutdown": "Leállítás",
"Shutdown Complete": "Leállítás kész", "Shutdown Complete": "Leállítás kész",
"Simple": "Egyszerű", "Simple": "Egyszerű",
"Simple File Versioning": "Egyszerű fájlverzió-követés", "Simple File Versioning": "Egyszerű fájlverzió-követés",
+1 -1
View File
@@ -322,7 +322,7 @@
"Show diff with previous version": "Tampilkan perbedaan dengan versi sebelumnya", "Show diff with previous version": "Tampilkan perbedaan dengan versi sebelumnya",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Ditampilkan sebagai ganti ID Perangkat dalam status gugus. Akan diumumkan ke perangkat lain sebagai nama bawaan opsional.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Ditampilkan sebagai ganti ID Perangkat dalam status gugus. Akan diumumkan ke perangkat lain sebagai nama bawaan opsional.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Ditampilkan sebagai ganti ID Perangkat dalam status gugus. Akan diubah menjadi nama yang perangkat umumkan jika tidak diisi.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Ditampilkan sebagai ganti ID Perangkat dalam status gugus. Akan diubah menjadi nama yang perangkat umumkan jika tidak diisi.",
"Shut Down": "Matikan", "Shutdown": "Matikan",
"Shutdown Complete": "Pematian Selesai", "Shutdown Complete": "Pematian Selesai",
"Simple File Versioning": "Pemversian Berkas Sederhana", "Simple File Versioning": "Pemversian Berkas Sederhana",
"Single level wildcard (matches within a directory only)": "Wildcard tingkat tunggal (cocok hanya dalam satu direktori saja)", "Single level wildcard (matches within a directory only)": "Wildcard tingkat tunggal (cocok hanya dalam satu direktori saja)",
+1 -1
View File
@@ -370,7 +370,7 @@
"Show diff with previous version": "Mostra le differenze con la versione precedente", "Show diff with previous version": "Mostra le differenze con la versione precedente",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Visibile al posto dell'ID Dispositivo nello stato del cluster. Negli altri dispositivi verrà presentato come nome predefinito opzionale.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Visibile al posto dell'ID Dispositivo nello stato del cluster. Negli altri dispositivi verrà presentato come nome predefinito opzionale.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Visibile al posto dell'ID Dispositivo nello stato del cluster. Se viene lasciato vuoto, verrà utilizzato il nome proposto dal dispositivo.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Visibile al posto dell'ID Dispositivo nello stato del cluster. Se viene lasciato vuoto, verrà utilizzato il nome proposto dal dispositivo.",
"Shut Down": "Arresta", "Shutdown": "Arresta",
"Shutdown Complete": "Arresto Eseguito", "Shutdown Complete": "Arresto Eseguito",
"Simple": "Semplice", "Simple": "Semplice",
"Simple File Versioning": "Controllo Versione Semplice", "Simple File Versioning": "Controllo Versione Semplice",
+1 -1
View File
@@ -311,7 +311,7 @@
"Show diff with previous version": "前バージョンとの差分を表示", "Show diff with previous version": "前バージョンとの差分を表示",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "ステータス画面でデバイスIDの代わりに表示されます。他のデバイスに対してもデフォルトの名前として通知されます。", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "ステータス画面でデバイスIDの代わりに表示されます。他のデバイスに対してもデフォルトの名前として通知されます。",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "ステータス画面でデバイスIDの代わりに表示されます。空欄にすると相手側デバイスが通知してきた名前で更新されます。", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "ステータス画面でデバイスIDの代わりに表示されます。空欄にすると相手側デバイスが通知してきた名前で更新されます。",
"Shut Down": "シャットダウン", "Shutdown": "シャットダウン",
"Shutdown Complete": "シャットダウン完了", "Shutdown Complete": "シャットダウン完了",
"Simple File Versioning": "単純バージョン管理", "Simple File Versioning": "単純バージョン管理",
"Single level wildcard (matches within a directory only)": "ワイルドカード (単一のディレクトリ内だけでマッチします)", "Single level wildcard (matches within a directory only)": "ワイルドカード (単一のディレクトリ内だけでマッチします)",
+1 -4
View File
@@ -82,7 +82,6 @@
"Custom Range": "사용자 설정 기간", "Custom Range": "사용자 설정 기간",
"Danger!": "위험!", "Danger!": "위험!",
"Database Location": "데이터베이스 위치", "Database Location": "데이터베이스 위치",
"Debug": "디버그",
"Debugging Facilities": "디버그 기능", "Debugging Facilities": "디버그 기능",
"Default": "기본값", "Default": "기본값",
"Default Configuration": "기본 설정", "Default Configuration": "기본 설정",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "수신 속도 제한(KiB/s)", "Incoming Rate Limit (KiB/s)": "수신 속도 제한(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.": "사용자 또는 비밀번호가 올바르지 않습니다.", "Incorrect user name or password.": "사용자 또는 비밀번호가 올바르지 않습니다.",
"Info": "정보",
"Internally used paths:": "내부적으로 사용되는 경로:", "Internally used paths:": "내부적으로 사용되는 경로:",
"Introduced By": "소개한 기기", "Introduced By": "소개한 기기",
"Introducer": "소개자", "Introducer": "소개자",
@@ -229,7 +227,6 @@
"Learn more": "더 알아보기", "Learn more": "더 알아보기",
"Learn more at {%url%}": "자세한 내용은 {{url}}을 참조하십시오.", "Learn more at {%url%}": "자세한 내용은 {{url}}을 참조하십시오.",
"Limit": "제한", "Limit": "제한",
"Limit Bandwidth in LAN": "근거리 통신망(LAN)에 속도 제한 적용",
"Listener Failures": "대기자 실패", "Listener Failures": "대기자 실패",
"Listener Status": "대기자 현황", "Listener Status": "대기자 현황",
"Listeners": "대기자", "Listeners": "대기자",
@@ -373,7 +370,7 @@
"Show diff with previous version": "이전 버전과의 diff 보기", "Show diff with previous version": "이전 버전과의 diff 보기",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "기기 아이디를 대신해 기기 목록에서 나타납니다. 다른 기기에 선택적 기본값 이름으로 통보됩니다.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "기기 아이디를 대신해 기기 목록에서 나타납니다. 다른 기기에 선택적 기본값 이름으로 통보됩니다.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "기기 아이디를 대신해 기기 목록에서 나타납니다. 비워 둘 경우 다른 기기에서 통보받은 이름으로 갱신됩니다.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "기기 아이디를 대신해 기기 목록에서 나타납니다. 비워 둘 경우 다른 기기에서 통보받은 이름으로 갱신됩니다.",
"Shut Down": "종료", "Shutdown": "종료",
"Shutdown Complete": "종료 완료", "Shutdown Complete": "종료 완료",
"Simple": "간단", "Simple": "간단",
"Simple File Versioning": "간단한 파일 버전 관리", "Simple File Versioning": "간단한 파일 버전 관리",
+1 -1
View File
@@ -337,7 +337,7 @@
"Show diff with previous version": "Rodyti skirtumus su ankstesne versija", "Show diff with previous version": "Rodyti skirtumus su ankstesne versija",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Grupės būsenoje rodomas vietoje įrenginio vardo. Kiti įrenginiai matys kaip pasirinktinį vardą.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Grupės būsenoje rodomas vietoje įrenginio vardo. Kiti įrenginiai matys kaip pasirinktinį vardą.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Grupės būsenoje rodomas vietoje įrenginio vardo. Bus atnaujintas į įrenginio vardą jei nieko neįrašysite.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Grupės būsenoje rodomas vietoje įrenginio vardo. Bus atnaujintas į įrenginio vardą jei nieko neįrašysite.",
"Shut Down": "Išjungti", "Shutdown": "Išjungti",
"Shutdown Complete": "Sėkmingai išjungta", "Shutdown Complete": "Sėkmingai išjungta",
"Simple File Versioning": "Supaprastintas versijų valdymas", "Simple File Versioning": "Supaprastintas versijų valdymas",
"Single level wildcard (matches within a directory only)": "Vieno lygio pakaitos simbolis (atitinka tik vieną katalogo lygį)", "Single level wildcard (matches within a directory only)": "Vieno lygio pakaitos simbolis (atitinka tik vieną katalogo lygį)",
+1 -1
View File
@@ -339,7 +339,7 @@
"Show diff with previous version": "Vis diff med forrige version", "Show diff with previous version": "Vis diff med forrige version",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vis i stedet for enhets-ID i gruppestatus. Vil bli kringkastet til andre enheter som et valgfritt forvalgsnavn.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vis i stedet for enhets-ID i gruppestatus. Vil bli kringkastet til andre enheter som et valgfritt forvalgsnavn.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vist i stedet for mappe-ID i gruppestatus. Vil bli oppdatert til navnet enheten kringkaster dersom tomt.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vist i stedet for mappe-ID i gruppestatus. Vil bli oppdatert til navnet enheten kringkaster dersom tomt.",
"Shut Down": "Avslutt", "Shutdown": "Avslutt",
"Shutdown Complete": "Avslutning fullført", "Shutdown Complete": "Avslutning fullført",
"Simple": "Enkel", "Simple": "Enkel",
"Simple File Versioning": "Enkel versjonskontroll", "Simple File Versioning": "Enkel versjonskontroll",
+3 -9
View File
@@ -27,7 +27,6 @@
"Allowed Networks": "Toegestane netwerken", "Allowed Networks": "Toegestane netwerken",
"Alphabetic": "Alfabetisch", "Alphabetic": "Alfabetisch",
"Altered by ignoring deletes.": "Veranderd door het negeren van verwijderingen.", "Altered by ignoring deletes.": "Veranderd door het negeren van verwijderingen.",
"Always turned on when the folder type is \"{%foldertype%}\".": "Altijd aanzetten als het map-type \"{{foldertype}}\" is.",
"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.": "Een externe opdracht regelt het versiebeheer. Hij moet het bestand verwijderen uit de gedeelde map. Als het pad naar de toepassing spaties bevat, moet dit tussen aanhalingstekens geplaatst worden.", "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.": "Een externe opdracht regelt het versiebeheer. Hij moet het bestand verwijderen uit de gedeelde map. Als het pad naar de toepassing spaties bevat, moet dit tussen aanhalingstekens geplaatst worden.",
"Anonymous Usage Reporting": "Anonieme gebruikersstatistieken", "Anonymous Usage Reporting": "Anonieme gebruikersstatistieken",
"Anonymous usage report format has changed. Would you like to move to the new format?": "Het formaat voor anonieme gebruikersrapporten is gewijzigd. Wil je naar het nieuwe formaat overschakelen?", "Anonymous usage report format has changed. Would you like to move to the new format?": "Het formaat voor anonieme gebruikersrapporten is gewijzigd. Wil je naar het nieuwe formaat overschakelen?",
@@ -53,7 +52,6 @@
"Body:": "Inhoud:", "Body:": "Inhoud:",
"Bugs": "Bugs", "Bugs": "Bugs",
"Cancel": "Annuleren", "Cancel": "Annuleren",
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "Kan niet aangezet worden als het map-type \"{{foldertype}}\" is.",
"Changelog": "Wijzigingenlogboek", "Changelog": "Wijzigingenlogboek",
"Clean out after": "Opruimen na", "Clean out after": "Opruimen na",
"Cleaning Versions": "Versies opruimen", "Cleaning Versions": "Versies opruimen",
@@ -82,7 +80,6 @@
"Custom Range": "Aangepast bereik", "Custom Range": "Aangepast bereik",
"Danger!": "Let op!", "Danger!": "Let op!",
"Database Location": "Locatie van database", "Database Location": "Locatie van database",
"Debug": "Debuggen",
"Debugging Facilities": "Debugmogelijkheden", "Debugging Facilities": "Debugmogelijkheden",
"Default": "Standaard", "Default": "Standaard",
"Default Configuration": "Standaardconfiguratie", "Default Configuration": "Standaardconfiguratie",
@@ -211,7 +208,6 @@
"Incoming Rate Limit (KiB/s)": "Begrenzing downloadsnelheid (KiB/s)", "Incoming Rate Limit (KiB/s)": "Begrenzing downloadsnelheid (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Verkeerde configuratie kan de inhoud van je map beschadigen en Syncthing onbruikbaar maken.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Verkeerde configuratie kan de inhoud van je map beschadigen en Syncthing onbruikbaar maken.",
"Incorrect user name or password.": "Onjuiste gebruikersnaam of wachtwoord.", "Incorrect user name or password.": "Onjuiste gebruikersnaam of wachtwoord.",
"Info": "Info",
"Internally used paths:": "Intern gebruikte paden:", "Internally used paths:": "Intern gebruikte paden:",
"Introduced By": "Geïntroduceerd door", "Introduced By": "Geïntroduceerd door",
"Introducer": "Introductie-apparaat", "Introducer": "Introductie-apparaat",
@@ -229,9 +225,8 @@
"Learn more": "Lees meer", "Learn more": "Lees meer",
"Learn more at {%url%}": "Meer informatie op {{url}}", "Learn more at {%url%}": "Meer informatie op {{url}}",
"Limit": "Begrenzing", "Limit": "Begrenzing",
"Limit Bandwidth in LAN": "Beperk de bandbreedte op het lokale netwerk", "Listener Failures": "Luisteraarfouten",
"Listener Failures": "Luisteraarsfouten", "Listener Status": "Luisteraarstatus",
"Listener Status": "Luisteraarsstatus",
"Listeners": "Luisteraars", "Listeners": "Luisteraars",
"Loading data...": "Gegevens laden...", "Loading data...": "Gegevens laden...",
"Loading...": "Laden...", "Loading...": "Laden...",
@@ -373,7 +368,7 @@
"Show diff with previous version": "Verschil met vorige versie weergeven", "Show diff with previous version": "Verschil met vorige versie weergeven",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Weergegeven in plaats van de apparaat-ID in de cluster-status. Zal aan andere apparaten voorgesteld worden als een optionele standaardnaam.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Weergegeven in plaats van de apparaat-ID in de cluster-status. Zal aan andere apparaten voorgesteld worden als een optionele standaardnaam.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Weergegeven in plaats van de apparaat-ID in de clusterstatus. Zal bijgewerkt worden met de naam die het apparaat voorstelt wanneer leeg gelaten.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Weergegeven in plaats van de apparaat-ID in de clusterstatus. Zal bijgewerkt worden met de naam die het apparaat voorstelt wanneer leeg gelaten.",
"Shut Down": "Afsluiten", "Shutdown": "Afsluiten",
"Shutdown Complete": "Afsluiten voltooid", "Shutdown Complete": "Afsluiten voltooid",
"Simple": "Eenvoudig", "Simple": "Eenvoudig",
"Simple File Versioning": "Eenvoudig versiebeheer", "Simple File Versioning": "Eenvoudig versiebeheer",
@@ -391,7 +386,6 @@
"Staggered File Versioning": "Gespreid versiebeheer", "Staggered File Versioning": "Gespreid versiebeheer",
"Start Browser": "Browser starten", "Start Browser": "Browser starten",
"Statistics": "Statistieken", "Statistics": "Statistieken",
"Stay logged in": "Blijf aangemeld",
"Stopped": "Gestopt", "Stopped": "Gestopt",
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Bewaart en synchroniseert alleen versleutelde gegevens. Mappen op alle verbonden apparaten moeten met hetzelfde wachtwoord ingesteld worden of ook van het type \"{{receiveEncrypted}}\" zijn.", "Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Bewaart en synchroniseert alleen versleutelde gegevens. Mappen op alle verbonden apparaten moeten met hetzelfde wachtwoord ingesteld worden of ook van het type \"{{receiveEncrypted}}\" zijn.",
"Subject:": "Onderwerp:", "Subject:": "Onderwerp:",
+1 -1
View File
@@ -187,7 +187,7 @@
"Show QR": "Vis QR", "Show QR": "Vis QR",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vist i staden for einings-ID-en i klyngjestatusen. Vil verta kringkasta til dei andre einingane som eit valfritt standardnamn.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vist i staden for einings-ID-en i klyngjestatusen. Vil verta kringkasta til dei andre einingane som eit valfritt standardnamn.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vist i staden for mappe-ID-en i klyngjestatuses. Vil verta oppdatert til namnet eininga kringkastar dersom tomt.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vist i staden for mappe-ID-en i klyngjestatuses. Vil verta oppdatert til namnet eininga kringkastar dersom tomt.",
"Shut Down": "Slå Av", "Shutdown": "Slå Av",
"Shutdown Complete": "Slått av", "Shutdown Complete": "Slått av",
"Simple File Versioning": "Enkel filutgåvehandtering", "Simple File Versioning": "Enkel filutgåvehandtering",
"Single level wildcard (matches within a directory only)": "Enkeltnivå-jokerteikn (søkjer berre i éi mappe)", "Single level wildcard (matches within a directory only)": "Enkeltnivå-jokerteikn (søkjer berre i éi mappe)",
+1 -4
View File
@@ -82,7 +82,6 @@
"Custom Range": "Niestandardowy okres", "Custom Range": "Niestandardowy okres",
"Danger!": "Niebezpieczeństwo!", "Danger!": "Niebezpieczeństwo!",
"Database Location": "Miejsce przechowywania bazy danych", "Database Location": "Miejsce przechowywania bazy danych",
"Debug": "Diagnozowanie błędów",
"Debugging Facilities": "Narzędzia do debugowania", "Debugging Facilities": "Narzędzia do debugowania",
"Default": "Domyślnie", "Default": "Domyślnie",
"Default Configuration": "Domyślne ustawienia", "Default Configuration": "Domyślne ustawienia",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Ograniczenie prędkości pobierania (KiB/s)", "Incoming Rate Limit (KiB/s)": "Ograniczenie prędkości pobierania (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Niepoprawne ustawienia mogą uszkodzić zawartość folderów oraz sprawić, że Syncthing przestanie działać.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Niepoprawne ustawienia mogą uszkodzić zawartość folderów oraz sprawić, że Syncthing przestanie działać.",
"Incorrect user name or password.": "Nieprawidłowa nazwa użytkownika lub hasło.", "Incorrect user name or password.": "Nieprawidłowa nazwa użytkownika lub hasło.",
"Info": "Informacje",
"Internally used paths:": "Ścieżki używane wewnętrznie:", "Internally used paths:": "Ścieżki używane wewnętrznie:",
"Introduced By": "Wprowadzony przez", "Introduced By": "Wprowadzony przez",
"Introducer": "Wprowadzający", "Introducer": "Wprowadzający",
@@ -229,7 +227,6 @@
"Learn more": "Dowiedz się więcej", "Learn more": "Dowiedz się więcej",
"Learn more at {%url%}": "Dowiedz się więcej na {{url}}", "Learn more at {%url%}": "Dowiedz się więcej na {{url}}",
"Limit": "Ograniczenie", "Limit": "Ograniczenie",
"Limit Bandwidth in LAN": "Ogranicz przepustowość w sieci lokalnej LAN",
"Listener Failures": "Błędy nasłuchujących", "Listener Failures": "Błędy nasłuchujących",
"Listener Status": "Stan nasłuchujących", "Listener Status": "Stan nasłuchujących",
"Listeners": "Nasłuchujący", "Listeners": "Nasłuchujący",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Pokaż diff z poprzednią wersją", "Show diff with previous version": "Pokaż diff z poprzednią wersją",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Widoczna na liście urządzeń zamiast identyfikatora urządzenia. Będzie anonsowana do innych urządzeń jako opcjonalna nazwa domyślna.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Widoczna na liście urządzeń zamiast identyfikatora urządzenia. Będzie anonsowana do innych urządzeń jako opcjonalna nazwa domyślna.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Widoczna na liście urządzeń zamiast identyfikatora urządzenia. Zostanie zaktualizowana do nazwy anonsowanej przez urządzenie, jeżeli pozostanie pusta.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Widoczna na liście urządzeń zamiast identyfikatora urządzenia. Zostanie zaktualizowana do nazwy anonsowanej przez urządzenie, jeżeli pozostanie pusta.",
"Shut Down": "Wyłącz", "Shutdown": "Wyłącz",
"Shutdown Complete": "Wyłączanie ukończone", "Shutdown Complete": "Wyłączanie ukończone",
"Simple": "Proste", "Simple": "Proste",
"Simple File Versioning": "Proste wersjonowanie plików", "Simple File Versioning": "Proste wersjonowanie plików",
+1 -4
View File
@@ -82,7 +82,6 @@
"Custom Range": "Intervalo de tempo", "Custom Range": "Intervalo de tempo",
"Danger!": "Perigo!", "Danger!": "Perigo!",
"Database Location": "Localização do banco de dados", "Database Location": "Localização do banco de dados",
"Debug": "Depuração",
"Debugging Facilities": "Facilidades de depuração", "Debugging Facilities": "Facilidades de depuração",
"Default": "Padrão", "Default": "Padrão",
"Default Configuration": "Configuração Padrão", "Default Configuration": "Configuração Padrão",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Limite de velocidade de recepção (KiB/s)", "Incoming Rate Limit (KiB/s)": "Limite de velocidade de recepção (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "A configuração incorreta poderá causar danos aos seus dados e tornar o Syncthing inoperante.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "A configuração incorreta poderá causar danos aos seus dados e tornar o Syncthing inoperante.",
"Incorrect user name or password.": "Nome de usuário ou senha incorretos.", "Incorrect user name or password.": "Nome de usuário ou senha incorretos.",
"Info": "Informações",
"Internally used paths:": "Caminhos usados internamente:", "Internally used paths:": "Caminhos usados internamente:",
"Introduced By": "Introduzido por", "Introduced By": "Introduzido por",
"Introducer": "Apresentador", "Introducer": "Apresentador",
@@ -229,7 +227,6 @@
"Learn more": "Saiba mais", "Learn more": "Saiba mais",
"Learn more at {%url%}": "Saiba mais em {{url}}", "Learn more at {%url%}": "Saiba mais em {{url}}",
"Limit": "Limite", "Limit": "Limite",
"Limit Bandwidth in LAN": "Limitar largura de banda na LAN",
"Listener Failures": "Falhas de Escuta", "Listener Failures": "Falhas de Escuta",
"Listener Status": "Status da Escuta", "Listener Status": "Status da Escuta",
"Listeners": "Escutadores", "Listeners": "Escutadores",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Mostrar diferenças da versão anterior", "Show diff with previous version": "Mostrar diferenças da versão anterior",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrado no lugar do ID do dispositivo no indicador de estado do grupo. Será divulgado aos outros dispositivos como um nome opcional e pré-definido.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrado no lugar do ID do dispositivo no indicador de estado do grupo. Será divulgado aos outros dispositivos como um nome opcional e pré-definido.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrado no lugar do ID do dispositivo no indicador de estado do grupo. Será atualizado para o nome que o dispositivo divulga, caso seja deixado em branco.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrado no lugar do ID do dispositivo no indicador de estado do grupo. Será atualizado para o nome que o dispositivo divulga, caso seja deixado em branco.",
"Shut Down": "Desligar", "Shutdown": "Desligar",
"Shutdown Complete": "Desligamento completado", "Shutdown Complete": "Desligamento completado",
"Simple": "Simples", "Simple": "Simples",
"Simple File Versioning": "Simples", "Simple File Versioning": "Simples",
+1 -1
View File
@@ -370,7 +370,7 @@
"Show diff with previous version": "Mostrar diferenças em relação à versão anterior", "Show diff with previous version": "Mostrar diferenças em relação à versão anterior",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Apresentado ao invés do ID do dispositivo no indicador de estado do grupo. Será divulgado aos outros dispositivos como um nome predefinido opcional.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Apresentado ao invés do ID do dispositivo no indicador de estado do grupo. Será divulgado aos outros dispositivos como um nome predefinido opcional.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Apresentado ao invés do ID do dispositivo no indicador de estado do grupo. Será actualizado para o nome que o dispositivo divulga, se for deixado em branco.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Apresentado ao invés do ID do dispositivo no indicador de estado do grupo. Será actualizado para o nome que o dispositivo divulga, se for deixado em branco.",
"Shut Down": "Desligar", "Shutdown": "Desligar",
"Shutdown Complete": "Encerramento completado", "Shutdown Complete": "Encerramento completado",
"Simple": "Simples", "Simple": "Simples",
"Simple File Versioning": "Simples", "Simple File Versioning": "Simples",
+1 -1
View File
@@ -312,7 +312,7 @@
"Show diff with previous version": "Show diff with previous version", "Show diff with previous version": "Show diff with previous version",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vizibil în locul ID-ului dispozitivului într-un grup. Va fi sugerat celorlalte dispozitive ca nume opţional. ", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vizibil în locul ID-ului dispozitivului într-un grup. Va fi sugerat celorlalte dispozitive ca nume opţional. ",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vizibil în locul ID-ului dispozitivului într-un grup. Va fi înlocuit de numele sugerat de dispozitiv daca nu este completat. ", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vizibil în locul ID-ului dispozitivului într-un grup. Va fi înlocuit de numele sugerat de dispozitiv daca nu este completat. ",
"Shut Down": "Opreşte", "Shutdown": "Opreşte",
"Shutdown Complete": "Oprește Complet", "Shutdown Complete": "Oprește Complet",
"Simple File Versioning": "Versiuni simple ale documentelor", "Simple File Versioning": "Versiuni simple ale documentelor",
"Single level wildcard (matches within a directory only)": "Asterisc de nivel simplu (corespunde doar unui fişier)", "Single level wildcard (matches within a directory only)": "Asterisc de nivel simplu (corespunde doar unui fişier)",
+3 -6
View File
@@ -82,7 +82,6 @@
"Custom Range": "Выбрать диапазон", "Custom Range": "Выбрать диапазон",
"Danger!": "Опасно!", "Danger!": "Опасно!",
"Database Location": "Расположение базы данных", "Database Location": "Расположение базы данных",
"Debug": "Дебаг (отладка)",
"Debugging Facilities": "Средства отладки", "Debugging Facilities": "Средства отладки",
"Default": "По умолчанию", "Default": "По умолчанию",
"Default Configuration": "Настройки по умолчанию", "Default Configuration": "Настройки по умолчанию",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Ограничение входящей скорости (КиБ/с)", "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.": "Неверное имя пользователя или пароль.", "Incorrect user name or password.": "Неверное имя пользователя или пароль.",
"Info": "Информация",
"Internally used paths:": "Внутренние используемые пути:", "Internally used paths:": "Внутренние используемые пути:",
"Introduced By": "Рекомендовано", "Introduced By": "Рекомендовано",
"Introducer": "Рекомендатель", "Introducer": "Рекомендатель",
@@ -229,7 +227,6 @@
"Learn more": "Узнать больше", "Learn more": "Узнать больше",
"Learn more at {%url%}": "Узнать больше на сайте {{url}}", "Learn more at {%url%}": "Узнать больше на сайте {{url}}",
"Limit": "Ограничение", "Limit": "Ограничение",
"Limit Bandwidth in LAN": "Ограничить пропускную способность в локальной сети",
"Listener Failures": "Ошибки прослушивателя", "Listener Failures": "Ошибки прослушивателя",
"Listener Status": "Статус прослушивателя", "Listener Status": "Статус прослушивателя",
"Listeners": "Прослушиватель", "Listeners": "Прослушиватель",
@@ -257,7 +254,7 @@
"Metadata Only": "Только метаданные", "Metadata Only": "Только метаданные",
"Minimum Free Disk Space": "Минимальное свободное место на диске", "Minimum Free Disk Space": "Минимальное свободное место на диске",
"Mod. Device": "Изм. устройство", "Mod. Device": "Изм. устройство",
"Mod. Time": "Время изменения", "Mod. Time": "Посл. изм.",
"More than a month ago": "Больше месяца назад", "More than a month ago": "Больше месяца назад",
"More than a week ago": "Больше недели назад", "More than a week ago": "Больше недели назад",
"More than a year ago": "Больше года назад", "More than a year ago": "Больше года назад",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Показать различия с предыдущей версией", "Show diff with previous version": "Показать различия с предыдущей версией",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Отображается вместо ID устройства в статусе группы. Будет разослан другим устройствам в качестве имени по умолчанию.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Отображается вместо ID устройства в статусе группы. Будет разослан другим устройствам в качестве имени по умолчанию.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Отображается вместо ID устройства в статусе группы. Если поле не заполнено, то будет установлено имя, передаваемое этим устройством.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Отображается вместо ID устройства в статусе группы. Если поле не заполнено, то будет установлено имя, передаваемое этим устройством.",
"Shut Down": "Выключить", "Shutdown": "Выключить",
"Shutdown Complete": "Выключение", "Shutdown Complete": "Выключение",
"Simple": "Просто", "Simple": "Просто",
"Simple File Versioning": "Простое управление версиями файлов", "Simple File Versioning": "Простое управление версиями файлов",
@@ -544,7 +541,7 @@
"items": "объекты", "items": "объекты",
"modified": "изменено", "modified": "изменено",
"permit": "разрешить", "permit": "разрешить",
"seconds": "секунд", "seconds": "сек.",
"theme": { "theme": {
"name": { "name": {
"black": "Чёрная", "black": "Чёрная",
+1 -1
View File
@@ -340,7 +340,7 @@
"Show diff with previous version": "පෙර අනුවාදය සමඟ වෙනස පෙන්වන්න", "Show diff with previous version": "පෙර අනුවාදය සමඟ වෙනස පෙන්වන්න",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "පොකුරු තත්ත්‍වයේ උපාංග හැඳුනුම්පත වෙනුවට පෙන්වා ඇත. විකල්ප පෙරනිමි නාමයක් ලෙස වෙනත් උපාංග වෙත ප්‍රචාරණය කරනු ඇත.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "පොකුරු තත්ත්‍වයේ උපාංග හැඳුනුම්පත වෙනුවට පෙන්වා ඇත. විකල්ප පෙරනිමි නාමයක් ලෙස වෙනත් උපාංග වෙත ප්‍රචාරණය කරනු ඇත.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "පොකුරු තත්ත්‍වයේ උපාංග හැඳුනුම්පත වෙනුවට පෙන්වා ඇත. හිස්ව තැබුවහොත් උපාංගය ප්‍රචාරණය කරන නමට යාවත්කාලීන වේ.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "පොකුරු තත්ත්‍වයේ උපාංග හැඳුනුම්පත වෙනුවට පෙන්වා ඇත. හිස්ව තැබුවහොත් උපාංගය ප්‍රචාරණය කරන නමට යාවත්කාලීන වේ.",
"Shut Down": "වසා දමන්න", "Shutdown": "වසා දමන්න",
"Shutdown Complete": "වසා දැමීම සම්පූර්ණයි", "Shutdown Complete": "වසා දැමීම සම්පූර්ණයි",
"Simple": "සරල", "Simple": "සරල",
"Simple File Versioning": "සරල ගොනු අනුවාදය", "Simple File Versioning": "සරල ගොනු අනුවාදය",
+1 -1
View File
@@ -366,7 +366,7 @@
"Show diff with previous version": "Ukázať rozdiely s predchádzajúcou verziou", "Show diff with previous version": "Ukázať rozdiely s predchádzajúcou verziou",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Zobrazované namiesto ID zariadenia v štatúte klastra. Toto pomenovanie bude oznamovať ostatným zariadeniam ako voliteľné predvolené pomenovanie.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Zobrazované namiesto ID zariadenia v štatúte klastra. Toto pomenovanie bude oznamovať ostatným zariadeniam ako voliteľné predvolené pomenovanie.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Zobrazované namiesto ID zariadenia v klastri. Ak je ponechané prázdne, bude nahradené pomenovaním, ktoré oznamuje zariadenie.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Zobrazované namiesto ID zariadenia v klastri. Ak je ponechané prázdne, bude nahradené pomenovaním, ktoré oznamuje zariadenie.",
"Shut Down": "Vypnutie", "Shutdown": "Vypnutie",
"Shutdown Complete": "Vypnutie ukončené", "Shutdown Complete": "Vypnutie ukončené",
"Simple": "Jednoduché", "Simple": "Jednoduché",
"Simple File Versioning": "Jednoduché verzie súborov", "Simple File Versioning": "Jednoduché verzie súborov",
+1 -1
View File
@@ -315,7 +315,7 @@
"Show diff with previous version": "Pokaži razliko s prejšnjo različico", "Show diff with previous version": "Pokaži razliko s prejšnjo različico",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Prikazano namesto ID-ja naprave v stanju gruče. Oglašuje se drugim napravam kot neobvezno privzeto ime.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Prikazano namesto ID-ja naprave v stanju gruče. Oglašuje se drugim napravam kot neobvezno privzeto ime.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Prikazano namesto ID-ja naprave v stanju gruče. Če ostane prazno, bo posodobljeno na ime, ki ga oglašuje naprava.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Prikazano namesto ID-ja naprave v stanju gruče. Če ostane prazno, bo posodobljeno na ime, ki ga oglašuje naprava.",
"Shut Down": "Izklopi", "Shutdown": "Izklopi",
"Shutdown Complete": "Izklop končan", "Shutdown Complete": "Izklop končan",
"Simple File Versioning": "Enostvno beleženje različic datotek", "Simple File Versioning": "Enostvno beleženje različic datotek",
"Single level wildcard (matches within a directory only)": "Enostopenjski nadomestni znak (ujema se samo v imeniku)", "Single level wildcard (matches within a directory only)": "Enostopenjski nadomestni znak (ujema se samo v imeniku)",
+3 -6
View File
@@ -82,7 +82,6 @@
"Custom Range": "Anpassat intervall", "Custom Range": "Anpassat intervall",
"Danger!": "Fara!", "Danger!": "Fara!",
"Database Location": "Databasplats", "Database Location": "Databasplats",
"Debug": "Felsökning",
"Debugging Facilities": "Felsökningsfunktioner", "Debugging Facilities": "Felsökningsfunktioner",
"Default": "Standard", "Default": "Standard",
"Default Configuration": "Standardkonfiguration", "Default Configuration": "Standardkonfiguration",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Ingående hastighetsgräns (KiB/s)", "Incoming Rate Limit (KiB/s)": "Ingående hastighetsgräns (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Inkorrekt konfiguration kan skada innehållet i mappen och få Syncthing att sluta fungera.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Inkorrekt konfiguration kan skada innehållet i mappen och få Syncthing att sluta fungera.",
"Incorrect user name or password.": "Felaktigt användarnamn eller lösenord.", "Incorrect user name or password.": "Felaktigt användarnamn eller lösenord.",
"Info": "Info",
"Internally used paths:": "Internt använda sökvägar:", "Internally used paths:": "Internt använda sökvägar:",
"Introduced By": "Introducerad av", "Introduced By": "Introducerad av",
"Introducer": "Introduktör", "Introducer": "Introduktör",
@@ -229,7 +227,6 @@
"Learn more": "Läs mer", "Learn more": "Läs mer",
"Learn more at {%url%}": "Läs mer på {{url}}", "Learn more at {%url%}": "Läs mer på {{url}}",
"Limit": "Gräns", "Limit": "Gräns",
"Limit Bandwidth in LAN": "Begränsa bandbredd i LAN",
"Listener Failures": "Lyssnarfel", "Listener Failures": "Lyssnarfel",
"Listener Status": "Lyssnarstatus", "Listener Status": "Lyssnarstatus",
"Listeners": "Lyssnare", "Listeners": "Lyssnare",
@@ -318,8 +315,8 @@
"Received data is already encrypted": "Mottagna data är redan krypterade", "Received data is already encrypted": "Mottagna data är redan krypterade",
"Recent Changes": "Senaste ändringar", "Recent Changes": "Senaste ändringar",
"Reduced by ignore patterns": "Minskas med ignoreringsmönster", "Reduced by ignore patterns": "Minskas med ignoreringsmönster",
"Relay LAN": "LAN-relä", "Relay LAN": "Relä LAN",
"Relay WAN": "WAN-relä", "Relay WAN": "Relä WAN",
"Release Notes": "Versionsanteckningar", "Release Notes": "Versionsanteckningar",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Utgåvskandidater innehåller de senaste funktionerna och korrigeringarna. De liknar de traditionella Syncthing-utgåvorna som kommer ut varannan vecka.", "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Utgåvskandidater innehåller de senaste funktionerna och korrigeringarna. De liknar de traditionella Syncthing-utgåvorna som kommer ut varannan vecka.",
"Remote Devices": "Fjärrenheter", "Remote Devices": "Fjärrenheter",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Visa skillnad med tidigare version", "Show diff with previous version": "Visa skillnad med tidigare version",
"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 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.", "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.",
"Shut Down": "Stäng av", "Shutdown": "Stäng av",
"Shutdown Complete": "Avstängning slutförd", "Shutdown Complete": "Avstängning slutförd",
"Simple": "Enkel", "Simple": "Enkel",
"Simple File Versioning": "Enkel filversionshantering", "Simple File Versioning": "Enkel filversionshantering",
+1 -4
View File
@@ -82,7 +82,6 @@
"Custom Range": "Özel Aralık", "Custom Range": "Özel Aralık",
"Danger!": "Tehlike!", "Danger!": "Tehlike!",
"Database Location": "Veritabanı Konumu", "Database Location": "Veritabanı Konumu",
"Debug": "Hata Ayıklama",
"Debugging Facilities": "Hata Ayıklama Olanakları", "Debugging Facilities": "Hata Ayıklama Olanakları",
"Default": "Varsayılan", "Default": "Varsayılan",
"Default Configuration": "Varsayılan Yapılandırma", "Default Configuration": "Varsayılan Yapılandırma",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Gelen Hız Sınırı (KiB/s)", "Incoming Rate Limit (KiB/s)": "Gelen Hız Sınırı (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Yanlış yapılandırma klasör içeriklerinize zarar verebilir ve Syncthing'i çalışamaz hale getirebilir.", "Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Yanlış yapılandırma klasör içeriklerinize zarar verebilir ve Syncthing'i çalışamaz hale getirebilir.",
"Incorrect user name or password.": "Yanlış kullanıcı adı ya da parola.", "Incorrect user name or password.": "Yanlış kullanıcı adı ya da parola.",
"Info": "Bilgi",
"Internally used paths:": "Dahili olarak kullanılan yollar:", "Internally used paths:": "Dahili olarak kullanılan yollar:",
"Introduced By": "Tanıtan", "Introduced By": "Tanıtan",
"Introducer": "Tanıtıcı", "Introducer": "Tanıtıcı",
@@ -229,7 +227,6 @@
"Learn more": "Daha fazla bilgi edinin", "Learn more": "Daha fazla bilgi edinin",
"Learn more at {%url%}": "{{url}} adresinde daha fazla bilgi edinin", "Learn more at {%url%}": "{{url}} adresinde daha fazla bilgi edinin",
"Limit": "Sınır", "Limit": "Sınır",
"Limit Bandwidth in LAN": "LAN'da Bant Genişliğini Sınırla",
"Listener Failures": "Dinleyici Hataları", "Listener Failures": "Dinleyici Hataları",
"Listener Status": "Dinleyici Durumu", "Listener Status": "Dinleyici Durumu",
"Listeners": "Dinleyiciler", "Listeners": "Dinleyiciler",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Önceki sürüm ile farklılıkları göster", "Show diff with previous version": "Önceki sürüm ile farklılıkları göster",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Küme durumunda Cihaz Kimliği yerine gösterilir. İsteğe bağlı varsayılan ad olarak diğer cihazlara duyurulacaktır.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Küme durumunda Cihaz Kimliği yerine gösterilir. İsteğe bağlı varsayılan ad olarak diğer cihazlara duyurulacaktır.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Küme durumunda Cihaz Kimliği yerine gösterilir. Boş bırakılırsa duyurulan cihaz adına güncellenecektir.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Küme durumunda Cihaz Kimliği yerine gösterilir. Boş bırakılırsa duyurulan cihaz adına güncellenecektir.",
"Shut Down": "Kapat", "Shutdown": "Kapat",
"Shutdown Complete": "Kapatma İşlemi Tamamlandı", "Shutdown Complete": "Kapatma İşlemi Tamamlandı",
"Simple": "Basit", "Simple": "Basit",
"Simple File Versioning": "Basit Dosya Sürümlendirme", "Simple File Versioning": "Basit Dosya Sürümlendirme",
+6 -9
View File
@@ -82,7 +82,6 @@
"Custom Range": "Обрати діапазон", "Custom Range": "Обрати діапазон",
"Danger!": "Небезпечно!", "Danger!": "Небезпечно!",
"Database Location": "Розташування бази даних", "Database Location": "Розташування бази даних",
"Debug": "Дебаг (налагодження)",
"Debugging Facilities": "Засоби налагодження", "Debugging Facilities": "Засоби налагодження",
"Default": "Типово", "Default": "Типово",
"Default Configuration": "Типові налаштування", "Default Configuration": "Типові налаштування",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "Ліміт швидкості завантаження (КіБ/с)", "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.": "Невірний логін або пароль.", "Incorrect user name or password.": "Невірний логін або пароль.",
"Info": "Інформація",
"Internally used paths:": "Шляхи, що використовуються внутрішньо:", "Internally used paths:": "Шляхи, що використовуються внутрішньо:",
"Introduced By": "Рекомендовано", "Introduced By": "Рекомендовано",
"Introducer": "Рекомендувач", "Introducer": "Рекомендувач",
@@ -229,7 +227,6 @@
"Learn more": "Дізнатися більше", "Learn more": "Дізнатися більше",
"Learn more at {%url%}": "Дізнайтесь більше за посиланням {{url}}", "Learn more at {%url%}": "Дізнайтесь більше за посиланням {{url}}",
"Limit": "Ліміт", "Limit": "Ліміт",
"Limit Bandwidth in LAN": "Обмеження пропускної здатності в локальній мережі",
"Listener Failures": "Помилки приймачів", "Listener Failures": "Помилки приймачів",
"Listener Status": "Стан приймача", "Listener Status": "Стан приймача",
"Listeners": "Приймачі", "Listeners": "Приймачі",
@@ -256,8 +253,8 @@
"Maximum total size": "Максимальний загальний розмір", "Maximum total size": "Максимальний загальний розмір",
"Metadata Only": "Тільки метадані", "Metadata Only": "Тільки метадані",
"Minimum Free Disk Space": "Мінімальний вільний простір на диску", "Minimum Free Disk Space": "Мінімальний вільний простір на диску",
"Mod. Device": "Модифікований пристрій", "Mod. Device": "Модифікований пристрій:",
"Mod. Time": "Час модифікації", "Mod. Time": "Час модифікації:",
"More than a month ago": "Більше місяця тому", "More than a month ago": "Більше місяця тому",
"More than a week ago": "Більше тижня тому", "More than a week ago": "Більше тижня тому",
"More than a year ago": "Більше року тому", "More than a year ago": "Більше року тому",
@@ -289,7 +286,7 @@
"Password": "Пароль", "Password": "Пароль",
"Path": "Шлях", "Path": "Шлях",
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Шлях до папки на локальному комп’ютері. Буде створений, якщо не існує. Символ тильди (~) може бути використаний як ярлик для", "Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Шлях до папки на локальному комп’ютері. Буде створений, якщо не існує. Символ тильди (~) може бути використаний як ярлик для",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Шлях, де повинні зберігатися версії (залиште порожнім для зберігання в .stversions усередині директорії).", "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Шлях, де повинні зберігатися версії (залиште порожнім для зберігання в .stversions усередині директорії)",
"Paths": "Шляхи", "Paths": "Шляхи",
"Pause": "Пауза", "Pause": "Пауза",
"Pause All": "Призупинити все", "Pause All": "Призупинити все",
@@ -373,7 +370,7 @@
"Show diff with previous version": "Показати відмінності від попередньої версії", "Show diff with previous version": "Показати відмінності від попередньої версії",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Показується замість ID пристрою в статусі кластера. Буде розголошено іншим вузлам як опціональне типове ім’я.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Показується замість ID пристрою в статусі кластера. Буде розголошено іншим вузлам як опціональне типове ім’я.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Показується замість ID пристрою в статусі кластера. Буде оновлено ім’ям, яке розголошене пристроєм, якщо залишити порожнім.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Показується замість ID пристрою в статусі кластера. Буде оновлено ім’ям, яке розголошене пристроєм, якщо залишити порожнім.",
"Shut Down": "Вимкнути", "Shutdown": "Вимкнути",
"Shutdown Complete": "Вимикання завершене", "Shutdown Complete": "Вимикання завершене",
"Simple": "Просте", "Simple": "Просте",
"Simple File Versioning": "Просте версіювання", "Simple File Versioning": "Просте версіювання",
@@ -450,7 +447,7 @@
"The number of versions must be a number and cannot be blank.": "Кількість версій повинна бути цифрою та не може бути порожньою.", "The number of versions must be a number and cannot be blank.": "Кількість версій повинна бути цифрою та не може бути порожньою.",
"The path cannot be blank.": "Шлях не може бути порожнім.", "The path cannot be blank.": "Шлях не може бути порожнім.",
"The rate limit is applied to the accumulated traffic of all connections to this device.": "Обмеження швидкості накладається на сумарний трафік всіх під'єднань до цього пристрою.", "The rate limit is applied to the accumulated traffic of all connections to this device.": "Обмеження швидкості накладається на сумарний трафік всіх під'єднань до цього пристрою.",
"The rate limit must be a non-negative number (0: no limit)": "Швидкість має бути додатнім числом", "The rate limit must be a non-negative number (0: no limit)": "Швидкість має бути додатнім числом.",
"The remote device has not accepted sharing this folder.": "Віддалений пристрій не прийняв спільний доступ до цієї папки.", "The remote device has not accepted sharing this folder.": "Віддалений пристрій не прийняв спільний доступ до цієї папки.",
"The remote device has paused this folder.": "Віддалений пристрій призупинив синхронізацію цієї папки.", "The remote device has paused this folder.": "Віддалений пристрій призупинив синхронізацію цієї папки.",
"The rescan interval must be a non-negative number of seconds.": "Інтервал повторного сканування повинен бути неід’ємною величиною.", "The rescan interval must be a non-negative number of seconds.": "Інтервал повторного сканування повинен бути неід’ємною величиною.",
@@ -465,7 +462,7 @@
"This is a major version upgrade.": "Це мажорне оновлення.", "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": "Час",
"Time the item was last modified": "Час останньої зміни елемента", "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:": "Щоб підключитися до пристрою Syncthing з назвою \"{{devicename}}\", додайте новий віддалений пристрій із свого боку за цим ID:", "To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "Щоб підключитися до пристрою Syncthing з назвою \"{{devicename}}\", додайте новий віддалений пристрій із свого боку за цим ID:",
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Аби застосувати правило, зазначте поле. Аби відмінити правило, залишить поле порожнім.", "To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Аби застосувати правило, зазначте поле. Аби відмінити правило, залишить поле порожнім.",
"Today": "Сьогодні", "Today": "Сьогодні",
+1 -1
View File
@@ -161,7 +161,7 @@
"Show QR": "Hiển thị QR", "Show QR": "Hiển thị QR",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Hiển thị thay cho ID th.bị trong trạng thái cụm. Sẽ được giới thiệu đến các th.bị khác như tên mặc định tuỳ chọn.", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Hiển thị thay cho ID th.bị trong trạng thái cụm. Sẽ được giới thiệu đến các th.bị khác như tên mặc định tuỳ chọn.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Hiển thị thay cho ID thiết bị trong trạng thái cụm. Nếu để trống sẽ được cập nhật thành tên mà thiết bị giới thiệu.", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Hiển thị thay cho ID thiết bị trong trạng thái cụm. Nếu để trống sẽ được cập nhật thành tên mà thiết bị giới thiệu.",
"Shut Down": "Tắt", "Shutdown": "Tắt",
"Shutdown Complete": "Tắt hoàn tất", "Shutdown Complete": "Tắt hoàn tất",
"Simple File Versioning": "Kiểu đơn giản", "Simple File Versioning": "Kiểu đơn giản",
"Single level wildcard (matches within a directory only)": "Ký tự thay thế đơn cấp (phù hợp với chỉ một thư mục)", "Single level wildcard (matches within a directory only)": "Ký tự thay thế đơn cấp (phù hợp với chỉ một thư mục)",
+1 -4
View File
@@ -82,7 +82,6 @@
"Custom Range": "自定义范围", "Custom Range": "自定义范围",
"Danger!": "危险!", "Danger!": "危险!",
"Database Location": "数据库位置", "Database Location": "数据库位置",
"Debug": "调试",
"Debugging Facilities": "调试功能", "Debugging Facilities": "调试功能",
"Default": "默认", "Default": "默认",
"Default Configuration": "默认配置", "Default Configuration": "默认配置",
@@ -211,7 +210,6 @@
"Incoming Rate Limit (KiB/s)": "传入速率限制(KiB/s", "Incoming Rate Limit (KiB/s)": "传入速率限制(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.": "用户名或密码不正确。", "Incorrect user name or password.": "用户名或密码不正确。",
"Info": "信息",
"Internally used paths:": "内部使用的路径:", "Internally used paths:": "内部使用的路径:",
"Introduced By": "介绍自", "Introduced By": "介绍自",
"Introducer": "作为中介", "Introducer": "作为中介",
@@ -229,7 +227,6 @@
"Learn more": "了解更多", "Learn more": "了解更多",
"Learn more at {%url%}": "了解更多请访问 {{url}}", "Learn more at {%url%}": "了解更多请访问 {{url}}",
"Limit": "限制", "Limit": "限制",
"Limit Bandwidth in LAN": "在局域网内限制带宽",
"Listener Failures": "监听程序失败", "Listener Failures": "监听程序失败",
"Listener Status": "监听程序状态", "Listener Status": "监听程序状态",
"Listeners": "监听程序", "Listeners": "监听程序",
@@ -373,7 +370,7 @@
"Show diff with previous version": "显示与以前版本的差异", "Show diff with previous version": "显示与以前版本的差异",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "在集群状态中显示该名称,而不是设备 ID。将作为可选的默认名称向其他设备通告。", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "在集群状态中显示该名称,而不是设备 ID。将作为可选的默认名称向其他设备通告。",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "在集群状态中显示该名称,而不是设备 ID。如果留空,将更新为设备通告的名称。", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "在集群状态中显示该名称,而不是设备 ID。如果留空,将更新为设备通告的名称。",
"Shut Down": "关闭", "Shutdown": "关闭",
"Shutdown Complete": "关闭完成", "Shutdown Complete": "关闭完成",
"Simple": "简单", "Simple": "简单",
"Simple File Versioning": "简单文件版本控制", "Simple File Versioning": "简单文件版本控制",
+1 -1
View File
@@ -340,7 +340,7 @@
"Show diff with previous version": "顯示與先前版本的差異", "Show diff with previous version": "顯示與先前版本的差異",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "在集群狀態中顯示該名稱,而不是設備 ID。將會作為當前設備的可選的默認名稱,報告給所有其他設備。", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "在集群狀態中顯示該名稱,而不是設備 ID。將會作為當前設備的可選的默認名稱,報告給所有其他設備。",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "在集群狀態中顯示該名稱,而不是設備 ID。如果設置為空,則會使用目標設備自報的默認名稱。", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "在集群狀態中顯示該名稱,而不是設備 ID。如果設置為空,則會使用目標設備自報的默認名稱。",
"Shut Down": "關閉", "Shutdown": "關閉",
"Shutdown Complete": "關閉完成", "Shutdown Complete": "關閉完成",
"Simple": "簡易", "Simple": "簡易",
"Simple File Versioning": "簡易版本控制", "Simple File Versioning": "簡易版本控制",
+1 -1
View File
@@ -368,7 +368,7 @@
"Show diff with previous version": "顯示與前一個版本的差異", "Show diff with previous version": "顯示與前一個版本的差異",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "代替裝置識別碼顯示在叢集狀態中。這段文字將會廣播到其他的裝置作為一個可選的預設名稱。", "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "代替裝置識別碼顯示在叢集狀態中。這段文字將會廣播到其他的裝置作為一個可選的預設名稱。",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "代替裝置識別碼顯示在叢集狀態中。本欄若未填寫則將被更新為此裝置所廣播的名稱。", "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "代替裝置識別碼顯示在叢集狀態中。本欄若未填寫則將被更新為此裝置所廣播的名稱。",
"Shut Down": "關閉", "Shutdown": "關閉",
"Shutdown Complete": "關閉完成", "Shutdown Complete": "關閉完成",
"Simple": "簡單", "Simple": "簡單",
"Simple File Versioning": "簡單檔案版本控制", "Simple File Versioning": "簡單檔案版本控制",
+1 -1
View File
@@ -1 +1 @@
var langPrettyprint = {"ar":"Arabic","bg":"Bulgarian","ca":"Catalan","ca@valencia":"Valencian","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","es":"Spanish","eu":"Basque","fil":"Filipino","fr":"French","fy":"Frisian","ga":"Irish","he-IL":"Hebrew (Israel)","hi":"Hindi","hr":"Croatian","hu":"Hungarian","id":"Indonesian","it":"Italian","ja":"Japanese","ko-KR":"Korean","lt":"Lithuanian","nl":"Dutch","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ro-RO":"Romanian","ru":"Russian","sk":"Slovak","sl":"Slovenian","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","zh-CN":"Chinese (Simplified Han script)","zh-HK":"Chinese (Traditional Han script, Hong Kong)","zh-TW":"Chinese (Traditional Han script)"} var langPrettyprint = {"ar":"Arabic","bg":"Bulgarian","ca":"Catalan","ca@valencia":"Valencian","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","es":"Spanish","eu":"Basque","fil":"Filipino","fr":"French","fy":"Frisian","ga":"Irish","he-IL":"Hebrew (Israel)","hi":"Hindi","hu":"Hungarian","id":"Indonesian","it":"Italian","ja":"Japanese","ko-KR":"Korean","lt":"Lithuanian","nl":"Dutch","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ro-RO":"Romanian","ru":"Russian","sk":"Slovak","sl":"Slovenian","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","zh-CN":"Chinese (Simplified Han script)","zh-HK":"Chinese (Traditional Han script, Hong Kong)","zh-TW":"Chinese (Traditional Han script)"}
+1 -1
View File
@@ -1 +1 @@
var validLangs = ["ar","bg","ca","ca@valencia","cs","da","de","el","en","en-GB","es","eu","fil","fr","fy","ga","he-IL","hi","hr","hu","id","it","ja","ko-KR","lt","nl","pl","pt-BR","pt-PT","ro-RO","ru","sk","sl","sv","tr","uk","zh-CN","zh-HK","zh-TW"] var validLangs = ["ar","bg","ca","ca@valencia","cs","da","de","el","en","en-GB","es","eu","fil","fr","fy","ga","he-IL","hi","hu","id","it","ja","ko-KR","lt","nl","pl","pt-BR","pt-PT","ro-RO","ru","sk","sl","sv","tr","uk","zh-CN","zh-HK","zh-TW"]

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