mirror of
https://github.com/syncthing/syncthing.git
synced 2025-12-31 01:49:09 -05:00
Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c74177699 | ||
|
|
9a5f7fbadf | ||
|
|
22c222bf75 | ||
|
|
258341f8bf | ||
|
|
f5ca213682 | ||
|
|
6768daec07 | ||
|
|
6201eebc98 | ||
|
|
decb967969 | ||
|
|
aac3750298 | ||
|
|
a94951becd | ||
|
|
7dc290c3ed | ||
|
|
50faa8f7ef | ||
|
|
5c87ceb392 | ||
|
|
6ffc8255b6 | ||
|
|
3354e60461 | ||
|
|
06365e5635 | ||
|
|
da99203dcd | ||
|
|
57ea8a1bf5 | ||
|
|
f72832d591 | ||
|
|
c0c18a568c | ||
|
|
b0b3abf76b | ||
|
|
c20ed80dc4 | ||
|
|
e2febf246e | ||
|
|
2cdeb1bf70 | ||
|
|
876609a0f0 | ||
|
|
744ef0d8ac | ||
|
|
8d6fb86ee0 | ||
|
|
13c3dac89c | ||
|
|
b5fc332782 | ||
|
|
4a8a8b294d | ||
|
|
92905d30e8 | ||
|
|
914eb77ca4 | ||
|
|
f560e8c850 | ||
|
|
2e3975e956 | ||
|
|
bd0c2bf237 | ||
|
|
f86deedd9c | ||
|
|
782bd08aad | ||
|
|
22242d51be | ||
|
|
ac7338f1f2 | ||
|
|
bdb25f9ba5 | ||
|
|
0e2a07d71a | ||
|
|
5e1cd0e71a | ||
|
|
5224f07ac8 | ||
|
|
d9664a946d | ||
|
|
8c61e0d6ab | ||
|
|
6c73617974 | ||
|
|
037934ec74 | ||
|
|
78a741d0be | ||
|
|
ebad9e2073 | ||
|
|
d68fa84055 | ||
|
|
d3ed4de4ed | ||
|
|
6bbd24de12 | ||
|
|
c63ca4f563 | ||
|
|
0e5ba3ca05 | ||
|
|
44b0f0b456 | ||
|
|
4aa2199d5b | ||
|
|
49798552f2 | ||
|
|
171b8139ab | ||
|
|
7fa699e159 | ||
|
|
5373e38ac8 | ||
|
|
41ef945b2b | ||
|
|
81ff31b8fc | ||
|
|
82fbcb96f8 | ||
|
|
37ede49077 | ||
|
|
0ba3abdee4 | ||
|
|
ab92f8520c | ||
|
|
0e67c036bb | ||
|
|
046bbdfbd4 | ||
|
|
c6c74e8291 | ||
|
|
59b1b0e1dc | ||
|
|
4b17c511f9 | ||
|
|
df318ed370 | ||
|
|
07ce3572a0 | ||
|
|
b64052bc26 | ||
|
|
7956e7d0ef | ||
|
|
d400e51422 | ||
|
|
674a99e9ae | ||
|
|
88cabb9e0a | ||
|
|
b7ba401c0b | ||
|
|
7505ea79a0 | ||
|
|
e1324a0e23 | ||
|
|
b7b9476e5a | ||
|
|
d1db7e3dd2 | ||
|
|
362da59396 | ||
|
|
66262392c3 | ||
|
|
48f9d323fa | ||
|
|
f69c0b550c | ||
|
|
32245435e2 | ||
|
|
2658369051 | ||
|
|
d50adb225b | ||
|
|
7da898f2d6 | ||
|
|
0d919bd79c | ||
|
|
f91e90a94f | ||
|
|
7ce20f197b | ||
|
|
2f26a95973 | ||
|
|
123941cf62 | ||
|
|
9c67d57c28 | ||
|
|
5b3466dc6e | ||
|
|
bca6854c03 | ||
|
|
c930b2e9e2 | ||
|
|
d7a257b391 | ||
|
|
7709ac33a7 | ||
|
|
1e2379df1b | ||
|
|
ea5c9176e1 | ||
|
|
cc1b003f21 | ||
|
|
38bd90e6f2 | ||
|
|
1c47fae206 | ||
|
|
79a758be3c | ||
|
|
c7cf3ef899 | ||
|
|
2c2e6cd0d5 | ||
|
|
b7dffc051e | ||
|
|
963e9a4071 | ||
|
|
b28899ac07 | ||
|
|
83f6da8dca | ||
|
|
1a29296d9d | ||
|
|
a7de4c68e3 | ||
|
|
7f23de4f03 | ||
|
|
ca89f12be6 | ||
|
|
ddfa82e990 | ||
|
|
61302c467c | ||
|
|
d6b4873eed | ||
|
|
1ea98a16b1 | ||
|
|
e2f3500df9 | ||
|
|
8b025af1e5 | ||
|
|
c4abe6f815 | ||
|
|
4c5e9cf921 | ||
|
|
74706bb02b | ||
|
|
5975772ed8 | ||
|
|
cf11fa4327 | ||
|
|
40580d8b9b | ||
|
|
e25e71cdde |
42
.github/ISSUE_TEMPLATE.md
vendored
42
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,42 +0,0 @@
|
||||
### DO NOT REPORT SECURITY ISSUES IN THIS ISSUE TRACKER
|
||||
|
||||
Instead, contact security@syncthing.net directly - see
|
||||
https://syncthing.net/security.html for more information.
|
||||
|
||||
### DO NOT POST SUPPORT REQUESTS OR GENERAL QUESTIONS IN THIS ISSUE TRACKER
|
||||
|
||||
Please use the forum at https://forum.syncthing.net/ where a large number of
|
||||
helpful people hang out. This issue tracker is for reporting bugs or feature
|
||||
requests directly to the developers. Worst case you might get a short
|
||||
"that's a bug, please report it on GitHub" response on the forum, in which
|
||||
case we thank you for your patience and following our advice. :)
|
||||
|
||||
### Please use the correct issue tracker
|
||||
|
||||
If your problem relates to a Syncthing wrapper or [sub-project](https://github.com/syncthing) such as [Syncthing for Android](https://github.com/syncthing/syncthing-android/issues), [SyncTrayzor](https://github.com/canton7/synctrayzor) or the [documentation](https://github.com/syncthing/docs/issues), please use their respective issue trackers.
|
||||
|
||||
### Does your log mention database corruption?
|
||||
|
||||
If your Syncthing log reports panics because of database corruption it is most likely a fault with your system's storage or memory. Affected log entries will contain lines starting with `panic: leveldb`. You will need to delete the index database to clear this, by running `syncthing -reset-database`.
|
||||
|
||||
### Please do post actual bug reports and feature requests.
|
||||
|
||||
If your issue is a bug report, replace this boilerplate with a description
|
||||
of the problem, being sure to include at least:
|
||||
|
||||
- what happened,
|
||||
- what you expected to happen instead, and
|
||||
- any steps to reproduce the problem.
|
||||
|
||||
Also fill out the version information below and add log output or
|
||||
screenshots as appropriate.
|
||||
|
||||
If your issue is a feature request, simply replace this template text in
|
||||
its entirety.
|
||||
|
||||
### Version Information
|
||||
|
||||
Syncthing Version: v1.x.y
|
||||
OS Version: Windows 7 / Ubuntu 14.04 / ...
|
||||
Browser Version: (if applicable, for GUI issues)
|
||||
|
||||
13
.github/ISSUE_TEMPLATE/01-feature.md
vendored
Normal file
13
.github/ISSUE_TEMPLATE/01-feature.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: If you're just not sure how to do something, see "ask a question".
|
||||
labels: enhancement, needs-triage
|
||||
---
|
||||
|
||||
### Include required information
|
||||
|
||||
Please be sure to include at least:
|
||||
|
||||
- what problem your new feature would solve
|
||||
- how or why you think it is generally useful (i.e., not just for you)
|
||||
- what alternatives or workarounds you considered
|
||||
23
.github/ISSUE_TEMPLATE/02-bug.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/02-bug.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: If you're actually looking for support, see "ask a question".
|
||||
labels: bug, needs-triage
|
||||
---
|
||||
|
||||
### Does your log mention database corruption?
|
||||
|
||||
If your Syncthing log reports panics because of database corruption it is
|
||||
most likely a fault with your system's storage or memory. Affected log
|
||||
entries will contain lines starting with `panic: leveldb`. You will need to
|
||||
delete the index database to clear this, by running `syncthing
|
||||
-reset-database`.
|
||||
|
||||
### Include required information
|
||||
|
||||
Please be sure to include at least:
|
||||
|
||||
- which version of Syncthing and what operating system you are using
|
||||
- browser and version, if applicable
|
||||
- what happened,
|
||||
- what you expected to happen instead, and
|
||||
- any steps to reproduce the problem.
|
||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Ask a question
|
||||
url: https://forum.syncthing.net/
|
||||
about: Ask questions, get support, and discuss with other community members.
|
||||
- name: Android issues
|
||||
url: https://github.com/syncthing/syncthing-android/issues/
|
||||
about: The Android app has its own issue tracker.
|
||||
52
.github/SECURITY.md
vendored
52
.github/SECURITY.md
vendored
@@ -1,48 +1,10 @@
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you believe that you've found a Syncthing-related security vulnerability, please report it by sending email to the address security@syncthing.net. The PGP key for security@syncthing.net (B683AD7B76CAB013) below can be used to send encrypted mail or to verify responses received from that address.
|
||||
If you believe that you've found a Syncthing-related security vulnerability,
|
||||
please report it by sending email to the address security@syncthing.net. The
|
||||
[PGP key for security@syncthing.net
|
||||
(B683AD7B76CAB013)](https://syncthing.net/security-key.txt) can be used to
|
||||
send encrypted mail or to verify responses received from that address.
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1
|
||||
|
||||
mQENBFShFlIBCACsW346HYskhKhxrdZMjyU5Ntsjvg6/ogqINDPoL10/oaIP0G+t
|
||||
7zzC0K5Cq29ix43kNNLKTJNyPkdTeaJEcqslMUt6tovjHwoKJ073GP0W3KsNvBRg
|
||||
ffCZOAexGfOsBSL9KHaYGK67Py3TFgtN1H/EmboU1arrLfAMrmqOip++EGqOxjse
|
||||
gH0qk7Mk1TqEC5Xh3NGE7r1UobAlqdUv5E3v7U11NhAdP1zu/XZ/zvP5mwVQJMLv
|
||||
iZyeWGliNI8nEeRjYw+S85f4gq7H2mgoeNBN4WwwK1hhz9qpvCsgPW3XqlExTPI4
|
||||
1vM4PxpiFIuF0zuy2OwsmjrpTCZeBscr4Tj5ABEBAAG0K1N5bmN0aGluZyBTZWN1
|
||||
cml0eSA8c2VjdXJpdHlAc3luY3RoaW5nLm5ldD6JATgEEwECACIFAlShFlICGwMG
|
||||
CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELaDrXt2yrATB1UH/jnnIa6DekCA
|
||||
2V36N/2+pFSNLVWeoZQxZ9ne9S7WSubaoK4oCWiuChPSAy5hagnKnNA3a9wrz5iN
|
||||
0hgCA88NnTU18biZW6HX8xWEd3dnY3fX1sG0XdHuKlFria8ByfcrbShf/CttXkEd
|
||||
Y5qPHH9aLIMtksBS1MIsRYrOCHiLNYFCKlbjDDCGT3tuk/yaU7aBAFVPIag54afC
|
||||
zZAIvTIgRruLWkNT/sSEJx9ekhJzO/+pXNbSSHwhoj5OJh7sQjZWwPzNazelk48R
|
||||
+ku8VpB5Wxgk2MnJPf1RxF+7saBAaeAVZsJcPN+Jp7u9LCFelIRn1ISsHbhLhyqL
|
||||
cPXqllltLCKJAhwEEAECAAYFAlShFlsACgkQSfWuwLzlJMcEpA//VvZYHGZgZMM0
|
||||
bBkYnjManYnJkHSQ2pHsjquSFH+fbfq2FxxTk/nQ/IAvBzt8NDTT3ylPOmsl4A8q
|
||||
r8BxsRNENhU7zDQrKC5NtYUrzXhPGo8qfDwkeLyqd2msUvHn7EH3PNgiN2QaFWxE
|
||||
21FqoXIpERKJRgRtv1SYZoMyNGjmT2hta1ZbwEfrPJnzjYhneoUGsRApG7p+uPqe
|
||||
4LRpbG3Fa2vBm/UWUrOe+6jPzvMokjIJbdK0IjXamFAzwYW5fSZaFa94mR6L5f5m
|
||||
X8Dhp66mBRTx7qk6ldEqptvaYGqihaWP1xbDaApQsGHQujtcBYGp+edlkabuW5h7
|
||||
stl/7QTFkEPqHT4ybxEX0rLoFUGq56WUlKp27z40keStaXMgfrsxJtkz66Xs8vU4
|
||||
7qZcLAcPsin+y0toqavtwtM/L7uCMu1yhbFRGJ+JL6saJAqzwS8l7r6E2R7OnVj1
|
||||
BdASgxx1TgzW6ZFW5p1Iy6mtpkBypsnp8s3UcP3GFRnQe9gi1EXHjzuZAUGafe4Q
|
||||
juvJ8t8xIcQMFuAylNIVyXvIWJoehqsVY9EBgVtE4y1SRh8XTT3Tddn8ab5fl7uh
|
||||
HWAY8cRlv6WIOhK8w8oroiYx0SID8jMeEwJBS4DL7qWtJMkDo8ZEJiB+Pkd963MX
|
||||
05QXt33AvJJ9PmbGCHkcH7198tCmA+e5AQ0EVKEWUgEIAPGczHpa6NdxY0pm+tIp
|
||||
btiA6gdPE70pJYgJTKX7siCQ2w770H3CBSKmqEXadr7WnfIgUYIDaSxadeGzB/Mn
|
||||
3SHCYRCqbA7mwu2k4wNNvCEM0xZqFAvaDJ4avlZ5oiMT8IFHKsjC77nkhmfXaIGt
|
||||
hn10H2MFADjvJYul7vR+Ghg1wGhTGWo2u7VVj9BI+AfvnWaouFI0cx2KNWEI/Ocj
|
||||
z6jk8nmC3yOEFQECM/hF4lkAOv9CQUa8UcvAr31trzawmV1iSsKjmVZgqd0N4T8f
|
||||
hUikqUPZGNCRcqEUffTzggIyGPbedFnZw9Di7o1xByxyTrZycemAVqaVGF+9nFLG
|
||||
pccAEQEAAYkBHwQYAQIACQUCVKEWUgIbDAAKCRC2g617dsqwEzrjB/9q0T8A4XUE
|
||||
p0g6xq86jhmh4jlEedxrfXUL3R6ejFtuKMThulxEP0xiQ7xLzBhOnvyxLCsVbjp8
|
||||
0JtJTVCq44UzUiIBuVNRoYG29uXuTUL2UtI27VhjFxMzLDwZL97tbGR6lzdM/+U5
|
||||
9PC+PIvS0yz13z2t3/x3KUOnBgxZnpy9h4AdKwjrNVtnQdGDXSKlJBLb57TFcS94
|
||||
f3roZ5Gpw3AWYSmSSiZWbhks2UNzYSQ84LAKlV1NkktO+qRc/pUqr6IxMjOKc7XP
|
||||
e8u1Nst6fN3GNqZOV+jUYs/fqrJgp1TUWjNTuf22Rl0Idz7XLPJKYFh9W7T/4MbU
|
||||
M7Q8GZuww1rk
|
||||
=No/v
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
You can read more about Syncthing security at
|
||||
https://syncthing.net/security/.
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -15,12 +15,5 @@ coverage.xml
|
||||
syncthing.sig
|
||||
RELEASE
|
||||
deb
|
||||
lib/auto/gui.files.go
|
||||
snapcraft.yaml
|
||||
prime/
|
||||
snap/
|
||||
parts/
|
||||
stage/
|
||||
*.snap
|
||||
*.bz2
|
||||
/repos
|
||||
|
||||
9
AUTHORS
9
AUTHORS
@@ -17,6 +17,7 @@ Aaron Bieber (qbit) <qbit@deftly.net>
|
||||
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>
|
||||
Alan Pope <alan@popey.com>
|
||||
Alberto Donato <albertodonato@users.noreply.github.com>
|
||||
Alessandro G. (alessandro.g89) <alessandro.g89@gmail.com>
|
||||
Alex Xu <alex.hello71@gmail.com>
|
||||
Alexander Graf (alex2108) <register-github@alex-graf.de>
|
||||
@@ -49,6 +50,7 @@ Benedikt Morbach <benedikt.morbach@googlemail.com>
|
||||
Benno Fünfstück <benno.fuenfstueck@gmail.com>
|
||||
Benny Ng (tpng) <benny.tpng@gmail.com>
|
||||
boomsquared <54829195+boomsquared@users.noreply.github.com>
|
||||
Boqin Qin <bobbqqin@bupt.edu.cn>
|
||||
Boris Rybalkin <ribalkin@gmail.com>
|
||||
Brandon Philips (philips) <brandon@ifup.org>
|
||||
Brendan Long (brendanlong) <self@brendanlong.com>
|
||||
@@ -95,6 +97,7 @@ georgespatton <georgespatton@users.noreply.github.com>
|
||||
ghjklw <malo@jaffre.info>
|
||||
Gilli Sigurdsson (gillisig) <gilli@vx.is>
|
||||
Graham Miln (grahammiln) <graham.miln@dssw.co.uk> <graham.miln@miln.eu>
|
||||
greatroar <61184462+greatroar@users.noreply.github.com>
|
||||
Han Boetes <han@boetes.org>
|
||||
Harrison Jones (harrisonhjones) <harrisonhjones@users.noreply.github.com>
|
||||
Heiko Zuerker (Smiley73) <heiko@zuerker.org>
|
||||
@@ -130,6 +133,7 @@ Keith Turner <kturner@apache.org>
|
||||
Kelong Cong (kc1212) <kc04bc@gmx.com> <kc1212@users.noreply.github.com>
|
||||
Ken'ichi Kamada (kamadak) <kamada@nanohz.org>
|
||||
Kevin Allen (ironmig) <kma1660@gmail.com>
|
||||
Kevin Bushiri (keevBush) <keevbush@gmail.com> <36192217+keevBush@users.noreply.github.com>
|
||||
Kevin White, Jr. (kwhite17) <kevinwhite1710@gmail.com>
|
||||
klemens <ka7@github.com>
|
||||
Kurt Fitzner (Kudalufi) <kurt@va1der.ca> <kurt.fitzner@gmail.com>
|
||||
@@ -147,6 +151,7 @@ Marc Pujol (kilburn) <kilburn@la3.org>
|
||||
Marcin Dziadus (marcindziadus) <dziadus.marcin@gmail.com>
|
||||
marco-m <marco.molteni@laposte.net>
|
||||
Marcus Legendre <marcus.legendre@gmail.com>
|
||||
Mario Majila <mariustshipichik@gmail.com>
|
||||
Mark Pulford (mpx) <mark@kyne.com.au>
|
||||
Mateusz Naściszewski (mateon1) <matin1111@wp.pl>
|
||||
Mateusz Ż <thedead4fun@live.com>
|
||||
@@ -160,14 +165,18 @@ MaximAL <almaximal@ya.ru>
|
||||
Maxime Thirouin <m@moox.io>
|
||||
Michael Jephcote (Rewt0r) <rewt0r@gmx.com> <Rewt0r@users.noreply.github.com>
|
||||
Michael Ploujnikov (plouj) <ploujj@gmail.com>
|
||||
Michael Rienstra <mrienstra@gmail.com>
|
||||
Michael Tilli (pyfisch) <pyfisch@gmail.com>
|
||||
Mike Boone <mike@boonedocks.net>
|
||||
MikeLund <MikeLund@users.noreply.github.com>
|
||||
MikolajTwarog <43782609+MikolajTwarog@users.noreply.github.com>
|
||||
Mingxuan Lin <gdlmx@users.noreply.github.com>
|
||||
mv1005 <49659413+mv1005@users.noreply.github.com>
|
||||
Nate Morrison (nrm21) <natemorrison@gmail.com>
|
||||
Nicholas Rishel (PrototypeNM1) <rishel.nick@gmail.com> <PrototypeNM1@users.noreply.github.com>
|
||||
Nico Stapelbroek <3368018+nstapelbroek@users.noreply.github.com>
|
||||
Nicolas Braud-Santoni <nicolas@braud-santoni.eu>
|
||||
Nicolas Perraut <n.perraut@gmail.com>
|
||||
Niels Peter Roest (Niller303) <nielsproest@hotmail.com> <seje.niels@hotmail.com>
|
||||
Nils Jakobi (thunderstorm99) <jakobi.nils@gmail.com>
|
||||
Nitroretro <43112364+Nitroretro@users.noreply.github.com>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
FROM golang:1.13 AS builder
|
||||
ARG GOVERSION=latest
|
||||
FROM golang:$GOVERSION AS builder
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
@@ -21,8 +22,5 @@ COPY --from=builder /src/script/docker-entrypoint.sh /bin/entrypoint.sh
|
||||
|
||||
ENV PUID=1000 PGID=1000 HOME=/var/syncthing
|
||||
|
||||
HEALTHCHECK --interval=1m --timeout=10s \
|
||||
CMD nc -z localhost 8384 || exit 1
|
||||
|
||||
ENV STGUIADDRESS=0.0.0.0:8384
|
||||
ENTRYPOINT ["/bin/entrypoint.sh", "/bin/syncthing", "-home", "/var/syncthing/config"]
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
# We will grab the Go compiler from the latest Go image.
|
||||
FROM golang:1.13 as go
|
||||
|
||||
# Otherwise we base on the snapcraft container as that is by far the
|
||||
# most complex and tricky thing to get installed and working...
|
||||
FROM snapcore/snapcraft
|
||||
|
||||
# Go
|
||||
COPY --from=go /usr/local/go /usr/local/go
|
||||
ENV PATH="/usr/local/go/bin:$PATH"
|
||||
ARG GOVERSION=latest
|
||||
FROM golang:$GOVERSION
|
||||
|
||||
# FPM to build Debian packages
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
FROM golang:1.13 AS builder
|
||||
ARG GOVERSION=latest
|
||||
FROM golang:$GOVERSION AS builder
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
FROM golang:1.13 AS builder
|
||||
ARG GOVERSION=latest
|
||||
FROM golang:$GOVERSION AS builder
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
|
||||
112
build.go
112
build.go
@@ -25,13 +25,11 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -323,9 +321,6 @@ func runCommand(cmd string, target target) {
|
||||
case "deb":
|
||||
buildDeb(target)
|
||||
|
||||
case "snap":
|
||||
buildSnap(target)
|
||||
|
||||
case "vet":
|
||||
metalintShort()
|
||||
|
||||
@@ -409,12 +404,9 @@ func install(target target, tags []string) {
|
||||
defer shouldCleanupSyso(sysoPath)
|
||||
}
|
||||
|
||||
for _, pkg := range target.buildPkgs {
|
||||
args := []string{"install", "-v"}
|
||||
args = appendParameters(args, tags, pkg)
|
||||
|
||||
runPrint(goCmd, args...)
|
||||
}
|
||||
args := []string{"install", "-v"}
|
||||
args = appendParameters(args, tags, target.buildPkgs...)
|
||||
runPrint(goCmd, args...)
|
||||
}
|
||||
|
||||
func build(target target, tags []string) {
|
||||
@@ -442,15 +434,12 @@ func build(target target, tags []string) {
|
||||
defer shouldCleanupSyso(sysoPath)
|
||||
}
|
||||
|
||||
for _, pkg := range target.buildPkgs {
|
||||
args := []string{"build", "-v"}
|
||||
args = appendParameters(args, tags, pkg)
|
||||
|
||||
runPrint(goCmd, args...)
|
||||
}
|
||||
args := []string{"build", "-v"}
|
||||
args = appendParameters(args, tags, target.buildPkgs...)
|
||||
runPrint(goCmd, args...)
|
||||
}
|
||||
|
||||
func appendParameters(args []string, tags []string, pkg string) []string {
|
||||
func appendParameters(args []string, tags []string, pkgs ...string) []string {
|
||||
if pkgdir != "" {
|
||||
args = append(args, "-pkgdir", pkgdir)
|
||||
}
|
||||
@@ -466,7 +455,7 @@ func appendParameters(args []string, tags []string, pkg string) []string {
|
||||
|
||||
if !debugBinary {
|
||||
// Regular binaries get version tagged and skip some debug symbols
|
||||
args = append(args, "-ldflags", ldflags(path.Base(pkg)))
|
||||
args = append(args, "-ldflags", ldflags())
|
||||
} else {
|
||||
// -gcflags to disable optimizations and inlining. Skip -ldflags
|
||||
// because `Could not launch program: decoding dwarf section info at
|
||||
@@ -475,7 +464,7 @@ func appendParameters(args []string, tags []string, pkg string) []string {
|
||||
args = append(args, "-gcflags", "-N -l")
|
||||
}
|
||||
|
||||
return append(args, pkg)
|
||||
return append(args, pkgs...)
|
||||
}
|
||||
|
||||
func buildTar(target target) {
|
||||
@@ -588,63 +577,29 @@ func buildDeb(target target) {
|
||||
runPrint("fpm", args...)
|
||||
}
|
||||
|
||||
func buildSnap(target target) {
|
||||
os.RemoveAll("snap")
|
||||
|
||||
tmpl, err := template.ParseFiles("snapcraft.yaml.template")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
f, err := os.Create("snapcraft.yaml")
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
snaparch := goarch
|
||||
if snaparch == "armhf" {
|
||||
goarch = "arm"
|
||||
} else if snaparch == "i386" {
|
||||
goarch = "386"
|
||||
}
|
||||
snapver := version
|
||||
if strings.HasPrefix(snapver, "v") {
|
||||
snapver = snapver[1:]
|
||||
}
|
||||
snapgrade := "devel"
|
||||
if matched, _ := regexp.MatchString(`^\d+\.\d+\.\d+(-rc.\d+)?$`, snapver); matched {
|
||||
snapgrade = "stable"
|
||||
}
|
||||
err = tmpl.Execute(f, map[string]string{
|
||||
"Version": snapver,
|
||||
"HostArchitecture": runtime.GOARCH,
|
||||
"TargetArchitecture": snaparch,
|
||||
"Grade": snapgrade,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
runPrint("snapcraft", "clean")
|
||||
build(target, []string{"noupgrade"})
|
||||
runPrint("snapcraft")
|
||||
}
|
||||
|
||||
func shouldBuildSyso(dir string) (string, error) {
|
||||
type M map[string]interface{}
|
||||
major, minor, patch, build := semanticVersion()
|
||||
version := getVersion()
|
||||
version = strings.TrimPrefix(version, "v")
|
||||
major, minor, patch := semanticVersion()
|
||||
bs, err := json.Marshal(M{
|
||||
"FixedFileInfo": M{
|
||||
"FileVersion": M{
|
||||
"Major": major,
|
||||
"Minor": minor,
|
||||
"Patch": patch,
|
||||
"Build": build,
|
||||
},
|
||||
"ProductVersion": M{
|
||||
"Major": major,
|
||||
"Minor": minor,
|
||||
"Patch": patch,
|
||||
},
|
||||
},
|
||||
"StringFileInfo": M{
|
||||
"FileDescription": "Open Source Continuous File Synchronization",
|
||||
"LegalCopyright": "The Syncthing Authors",
|
||||
"ProductVersion": getVersion(),
|
||||
"FileVersion": version,
|
||||
"ProductVersion": version,
|
||||
"ProductName": "Syncthing",
|
||||
},
|
||||
"IconPath": "assets/logo.ico",
|
||||
@@ -732,11 +687,11 @@ func listFiles(dir string) []string {
|
||||
|
||||
func rebuildAssets() {
|
||||
os.Setenv("SOURCE_DATE_EPOCH", fmt.Sprint(buildStamp()))
|
||||
runPrint(goCmd, "generate", "github.com/syncthing/syncthing/lib/auto", "github.com/syncthing/syncthing/cmd/strelaypoolsrv/auto")
|
||||
runPrint(goCmd, "generate", "github.com/syncthing/syncthing/lib/api/auto", "github.com/syncthing/syncthing/cmd/strelaypoolsrv/auto")
|
||||
}
|
||||
|
||||
func lazyRebuildAssets() {
|
||||
if shouldRebuildAssets("lib/auto/gui.files.go", "gui") || shouldRebuildAssets("cmd/strelaypoolsrv/auto/gui.files.go", "cmd/strelaypoolsrv/auto/gui") {
|
||||
if shouldRebuildAssets("lib/api/auto/gui.files.go", "gui") || shouldRebuildAssets("cmd/strelaypoolsrv/auto/gui.files.go", "cmd/strelaypoolsrv/auto/gui") {
|
||||
rebuildAssets()
|
||||
}
|
||||
}
|
||||
@@ -803,14 +758,13 @@ func transifex() {
|
||||
runPrint(goCmd, "run", "../../../../script/transifexdl.go")
|
||||
}
|
||||
|
||||
func ldflags(program string) string {
|
||||
func ldflags() string {
|
||||
b := new(strings.Builder)
|
||||
b.WriteString("-w")
|
||||
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.User=%s", buildUser())
|
||||
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Host=%s", buildHost())
|
||||
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Program=%s", program)
|
||||
if v := os.Getenv("EXTRA_LDFLAGS"); v != "" {
|
||||
fmt.Fprintf(b, " %s", v)
|
||||
}
|
||||
@@ -864,22 +818,18 @@ func getVersion() string {
|
||||
return "unknown-dev"
|
||||
}
|
||||
|
||||
func semanticVersion() (major, minor, patch, build int) {
|
||||
r := regexp.MustCompile(`v(?P<Major>\d+)\.(?P<Minor>\d+).(?P<Patch>\d+).*\+(?P<CommitsAhead>\d+)`)
|
||||
func semanticVersion() (major, minor, patch int) {
|
||||
r := regexp.MustCompile(`v(\d+)\.(\d+).(\d+)`)
|
||||
matches := r.FindStringSubmatch(getVersion())
|
||||
if len(matches) != 5 {
|
||||
return 0, 0, 0, 0
|
||||
if len(matches) != 4 {
|
||||
return 0, 0, 0
|
||||
}
|
||||
|
||||
var ints [4]int
|
||||
for i := 1; i < 5; i++ {
|
||||
value, err := strconv.Atoi(matches[i])
|
||||
if err != nil {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
ints[i-1] = value
|
||||
var ints [3]int
|
||||
for i, s := range matches[1:] {
|
||||
ints[i], _ = strconv.Atoi(s)
|
||||
}
|
||||
return ints[0], ints[1], ints[2], ints[3]
|
||||
return ints[0], ints[1], ints[2]
|
||||
}
|
||||
|
||||
func getBranchSuffix() string {
|
||||
@@ -1194,7 +1144,7 @@ func macosCodesign(file string) {
|
||||
}
|
||||
|
||||
if id := os.Getenv("CODESIGN_IDENTITY"); id != "" {
|
||||
bs, err := runError("codesign", "-s", id, file)
|
||||
bs, err := runError("codesign", "--options=runtime", "-s", id, file)
|
||||
if err != nil {
|
||||
log.Println("Codesign: signing failed:", string(bs))
|
||||
return
|
||||
|
||||
@@ -31,12 +31,14 @@ var (
|
||||
clientsMut sync.Mutex
|
||||
)
|
||||
|
||||
func sendReport(dsn, path string, report []byte) error {
|
||||
func sendReport(dsn, path string, report []byte, userID string) error {
|
||||
pkt, err := parseReport(path, report)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pkt.Interfaces = append(pkt.Interfaces, &raven.User{ID: userID})
|
||||
|
||||
clientsMut.Lock()
|
||||
defer clientsMut.Unlock()
|
||||
|
||||
|
||||
@@ -16,14 +16,19 @@ import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/sha256"
|
||||
)
|
||||
|
||||
const maxRequestSize = 1 << 20 // 1 MiB
|
||||
@@ -145,9 +150,12 @@ func (r *crashReceiver) servePut(reportID, fullPath string, w http.ResponseWrite
|
||||
|
||||
// Send the report to Sentry
|
||||
if r.dsn != "" {
|
||||
// Remote ID
|
||||
user := userIDFor(req)
|
||||
|
||||
go func() {
|
||||
// There's no need for the client to have to wait for this part.
|
||||
if err := sendReport(r.dsn, reportID, bs); err != nil {
|
||||
if err := sendReport(r.dsn, reportID, bs, user); err != nil {
|
||||
log.Println("Failed to send report:", err)
|
||||
}
|
||||
}()
|
||||
@@ -158,3 +166,20 @@ func (r *crashReceiver) servePut(reportID, fullPath string, w http.ResponseWrite
|
||||
func (r *crashReceiver) dirFor(base string) string {
|
||||
return filepath.Join(base[0:2], base[2:4])
|
||||
}
|
||||
|
||||
// userIDFor returns a string we can use as the user ID for the purpose of
|
||||
// counting affected users. It's the truncated hash of a salt, the user
|
||||
// remote IP, and the current month.
|
||||
func userIDFor(req *http.Request) string {
|
||||
addr := req.RemoteAddr
|
||||
if fwd := req.Header.Get("x-forwarded-for"); fwd != "" {
|
||||
addr = fwd
|
||||
}
|
||||
if host, _, err := net.SplitHostPort(addr); err == nil {
|
||||
addr = host
|
||||
}
|
||||
now := time.Now().Format("200601")
|
||||
salt := "stcrashreporter"
|
||||
hash := sha256.Sum256([]byte(salt + addr + now))
|
||||
return fmt.Sprintf("%x", hash[:8])
|
||||
}
|
||||
|
||||
@@ -92,20 +92,21 @@ func main() {
|
||||
showVersion := flag.Bool("version", false, "Show version")
|
||||
flag.Parse()
|
||||
|
||||
log.Println(build.LongVersion)
|
||||
log.Println(build.LongVersionFor("stdiscosrv"))
|
||||
if *showVersion {
|
||||
return
|
||||
}
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
log.Println("Failed to load keypair. Generating one, this might take a while...")
|
||||
cert, err = tlsutil.NewCertificate(certFile, keyFile, "stdiscosrv", 20*365)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to generate X509 key pair:", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
log.Fatalln("Failed to load keypair:", err)
|
||||
}
|
||||
|
||||
devID := protocol.NewDeviceID(cert.Certificate[0])
|
||||
log.Println("Server device ID is", devID)
|
||||
|
||||
|
||||
@@ -9,8 +9,15 @@
|
||||
<meta name="author" content=""/>
|
||||
|
||||
<title>Relay stats</title>
|
||||
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link rel="stylesheet" href="//use.fontawesome.com/releases/v5.0.13/css/all.css"/>
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css"/>
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css"/>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
|
||||
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
|
||||
crossorigin=""/>
|
||||
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
|
||||
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
|
||||
crossorigin=""></script>
|
||||
|
||||
<style>
|
||||
#map {
|
||||
@@ -38,7 +45,7 @@
|
||||
<div class="container">
|
||||
<h1>Relay Pool Data</h1>
|
||||
<div ng-if="relays === undefined" class="text-center">
|
||||
<img src="//cdnjs.cloudflare.com/ajax/libs/galleriffic/2.0.1/css/loader.gif" alt=""/>
|
||||
<img src="https://cdnjs.cloudflare.com/ajax/libs/galleriffic/2.0.1/css/loader.gif" alt=""/>
|
||||
<p>Please wait while we gather data</p>
|
||||
</div>
|
||||
<div>
|
||||
@@ -184,10 +191,9 @@
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript" src="//code.jquery.com/jquery-2.1.4.min.js"></script>
|
||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
|
||||
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?key=AIzaSyDk5WJ8s7ueLKb99X5DbQ-vkWtPDAKqYs0"></script>
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
|
||||
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
@@ -228,11 +234,12 @@
|
||||
numProxies: 0,
|
||||
uptimeSeconds: 0,
|
||||
};
|
||||
$scope.map = new google.maps.Map(document.getElementById('map'), {
|
||||
zoom: 1,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
});
|
||||
$scope.mapBounds = new google.maps.LatLngBounds();
|
||||
$scope.map = L.map('map').setView([40.90296, 1.90925], 2);
|
||||
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
{
|
||||
attribution: 'Leaflet',
|
||||
maxZoom: 17
|
||||
}).addTo($scope.map);
|
||||
$scope.tooltipTemplate = $('#infoTemplate').html();
|
||||
$scope.usedLocations = {};
|
||||
$scope.sortType = 'stats.numActiveSessions';
|
||||
@@ -279,8 +286,9 @@
|
||||
}
|
||||
});
|
||||
|
||||
$scope.map.fitBounds($scope.mapBounds);
|
||||
if ($scope.relays.length == 1) {
|
||||
//Center to only relay with zoom
|
||||
$scope.map.panTo(new L.LatLng(relays[0].location.latitude, relays[0].location.longitude));
|
||||
$scope.map.setZoom(13);
|
||||
}
|
||||
});
|
||||
@@ -300,44 +308,50 @@
|
||||
|
||||
var locParts = loc.split(',');
|
||||
|
||||
relay.marker = new google.maps.Marker({
|
||||
map: $scope.map,
|
||||
position: new google.maps.LatLng(locParts[0], locParts[1]),
|
||||
relay.marker = new L.Marker([relay.location.latitude, relay.location.longitude],{
|
||||
title: relay.url,
|
||||
});
|
||||
|
||||
var scope = $rootScope.$new(true);
|
||||
scope.relay = relay;
|
||||
|
||||
relay.marker.info = new google.maps.InfoWindow({
|
||||
content: $compile($scope.tooltipTemplate)(scope)[0],
|
||||
var icon = new L.Icon({
|
||||
iconSize: [18, 28], // size of the icon
|
||||
iconAnchor: [9, 28], // point of the icon which will correspond to marker's location
|
||||
shadowAnchor: [0, 0], // the same for the shadow
|
||||
popupAnchor: [0, -27], // popup anchor
|
||||
shadowSize: [0,0],
|
||||
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-red.png',
|
||||
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
|
||||
});
|
||||
|
||||
relay.marker = new L.marker(new L.latLng(locParts[0], locParts[1]),{icon})
|
||||
.bindPopup($compile($scope.tooltipTemplate)(scope)[0],{})
|
||||
.on('mouseover', function (e) {
|
||||
this.openPopup();
|
||||
}).on('mouseout', function (e) {
|
||||
this.closePopup();
|
||||
}).addTo($scope.map);
|
||||
|
||||
relay.showMarker = function() {
|
||||
relay.marker.info.open($scope.map, relay.marker);
|
||||
relay.marker.openPopup();
|
||||
}
|
||||
|
||||
|
||||
relay.hideMarker = function() {
|
||||
relay.marker.info.close();
|
||||
relay.marker.closePopup();
|
||||
}
|
||||
}
|
||||
|
||||
relay.marker.addListener('mouseover', relay.showMarker);
|
||||
relay.marker.addListener('mouseout', relay.hideMarker);
|
||||
|
||||
$scope.mapBounds.extend(relay.marker.position);
|
||||
}
|
||||
|
||||
function addCircleToMap(relay) {
|
||||
relay.marker.circle = new google.maps.Circle({
|
||||
strokeColor: '#FF0000',
|
||||
strokeOpacity: 0.8,
|
||||
strokeWeight: 2,
|
||||
fillColor: '#FF0000',
|
||||
fillOpacity: 0.35,
|
||||
map: $scope.map,
|
||||
center: relay.marker.position,
|
||||
radius: ((relay.stats.bytesProxied * 100) / $scope.totals.bytesProxied) * 10000
|
||||
});
|
||||
console.log(relay.location.latitude)
|
||||
L.circle([relay.location.latitude, relay.location.longitude],
|
||||
{
|
||||
radius: ((relay.stats.bytesProxied * 100) / $scope.totals.bytesProxied) * 10000,
|
||||
color: "FF0000",
|
||||
fillColor: "#FF0000",
|
||||
fillOpacity: 0.35,
|
||||
}).addTo($scope.map);
|
||||
}
|
||||
|
||||
function constructURI(url) {
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
// Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
|
||||
|
||||
//go:generate go run ../../script/genassets.go gui >auto/gui.go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -31,6 +26,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/syncthing/syncthing/cmd/strelaypoolsrv/auto"
|
||||
"github.com/syncthing/syncthing/lib/assets"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
"github.com/syncthing/syncthing/lib/relay/client"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
@@ -95,33 +91,35 @@ type result struct {
|
||||
}
|
||||
|
||||
var (
|
||||
testCert tls.Certificate
|
||||
knownRelaysFile = filepath.Join(os.TempDir(), "strelaypoolsrv_known_relays")
|
||||
listen = ":80"
|
||||
dir string
|
||||
evictionTime = time.Hour
|
||||
debug bool
|
||||
getLRUSize = 10 << 10
|
||||
getLimitBurst = 10
|
||||
getLimitAvg = 2
|
||||
postLRUSize = 1 << 10
|
||||
postLimitBurst = 2
|
||||
postLimitAvg = 2
|
||||
getLimit time.Duration
|
||||
postLimit time.Duration
|
||||
permRelaysFile string
|
||||
ipHeader string
|
||||
geoipPath string
|
||||
proto string
|
||||
statsRefresh = time.Minute / 2
|
||||
testCert tls.Certificate
|
||||
knownRelaysFile = filepath.Join(os.TempDir(), "strelaypoolsrv_known_relays")
|
||||
listen = ":80"
|
||||
dir string
|
||||
evictionTime = time.Hour
|
||||
debug bool
|
||||
getLRUSize = 10 << 10
|
||||
getLimitBurst = 10
|
||||
getLimitAvg = 2
|
||||
postLRUSize = 1 << 10
|
||||
postLimitBurst = 2
|
||||
postLimitAvg = 2
|
||||
getLimit time.Duration
|
||||
postLimit time.Duration
|
||||
permRelaysFile string
|
||||
ipHeader string
|
||||
geoipPath string
|
||||
proto string
|
||||
statsRefresh = time.Minute / 2
|
||||
requestQueueLen = 10
|
||||
requestProcessors = 1
|
||||
|
||||
getMut = sync.NewRWMutex()
|
||||
getMut = sync.NewMutex()
|
||||
getLRUCache *lru.Cache
|
||||
|
||||
postMut = sync.NewRWMutex()
|
||||
postMut = sync.NewMutex()
|
||||
postLRUCache *lru.Cache
|
||||
|
||||
requests = make(chan request, 10)
|
||||
requests chan request
|
||||
|
||||
mut = sync.NewRWMutex()
|
||||
knownRelays = make([]*relay, 0)
|
||||
@@ -134,6 +132,9 @@ const (
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetOutput(os.Stdout)
|
||||
log.SetFlags(log.Lshortfile)
|
||||
|
||||
flag.StringVar(&listen, "listen", listen, "Listen address")
|
||||
flag.StringVar(&dir, "keys", dir, "Directory where http-cert.pem and http-key.pem is stored for TLS listening")
|
||||
flag.BoolVar(&debug, "debug", debug, "Enable debug output")
|
||||
@@ -149,9 +150,13 @@ func main() {
|
||||
flag.StringVar(&geoipPath, "geoip", "GeoLite2-City.mmdb", "Path to GeoLite2-City database")
|
||||
flag.StringVar(&proto, "protocol", "tcp", "Protocol used for listening. 'tcp' for IPv4 and IPv6, 'tcp4' for IPv4, 'tcp6' for IPv6")
|
||||
flag.DurationVar(&statsRefresh, "stats-refresh", statsRefresh, "Interval at which to refresh relay stats")
|
||||
flag.IntVar(&requestQueueLen, "request-queue", requestQueueLen, "Queue length for incoming test requests")
|
||||
flag.IntVar(&requestProcessors, "request-processors", requestProcessors, "Number of request processor routines")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
requests = make(chan request, requestQueueLen)
|
||||
|
||||
getLimit = 10 * time.Second / time.Duration(getLimitAvg)
|
||||
postLimit = time.Minute / time.Duration(postLimitAvg)
|
||||
|
||||
@@ -167,7 +172,9 @@ func main() {
|
||||
|
||||
testCert = createTestCertificate()
|
||||
|
||||
go requestProcessor()
|
||||
for i := 0; i < requestProcessors; i++ {
|
||||
go requestProcessor()
|
||||
}
|
||||
|
||||
// Load relays from cache in the background.
|
||||
// Load them in a serial fashion to make sure any genuine requests
|
||||
@@ -256,88 +263,31 @@ func handleMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
func handleAssets(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Cache-Control", "no-cache, must-revalidate")
|
||||
|
||||
assets := auto.Assets()
|
||||
path := r.URL.Path[1:]
|
||||
if path == "" {
|
||||
path = "index.html"
|
||||
}
|
||||
|
||||
bs, ok := assets[path]
|
||||
content, ok := auto.Assets()[path]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
etag := fmt.Sprintf("%d", auto.Generated)
|
||||
modified := time.Unix(auto.Generated, 0).UTC()
|
||||
|
||||
w.Header().Set("Last-Modified", modified.Format(http.TimeFormat))
|
||||
w.Header().Set("Etag", etag)
|
||||
|
||||
mtype := mimeTypeForFile(path)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
|
||||
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modified.Add(time.Second).After(t) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
if match := r.Header.Get("If-None-Match"); match != "" {
|
||||
if strings.Contains(match, etag) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
}
|
||||
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
} else {
|
||||
// ungzip if browser not send gzip accepted header
|
||||
var gr *gzip.Reader
|
||||
gr, _ = gzip.NewReader(bytes.NewReader(bs))
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
gr.Close()
|
||||
}
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bs)))
|
||||
|
||||
w.Write(bs)
|
||||
}
|
||||
|
||||
func mimeTypeForFile(file string) string {
|
||||
// We use a built in table of the common types since the system
|
||||
// TypeByExtension might be unreliable. But if we don't know, we delegate
|
||||
// to the system.
|
||||
ext := filepath.Ext(file)
|
||||
switch ext {
|
||||
case ".htm", ".html":
|
||||
return "text/html"
|
||||
case ".css":
|
||||
return "text/css"
|
||||
case ".js":
|
||||
return "application/javascript"
|
||||
case ".json":
|
||||
return "application/json"
|
||||
case ".png":
|
||||
return "image/png"
|
||||
case ".ttf":
|
||||
return "application/x-font-ttf"
|
||||
case ".woff":
|
||||
return "application/x-font-woff"
|
||||
case ".svg":
|
||||
return "image/svg+xml"
|
||||
default:
|
||||
return mime.TypeByExtension(ext)
|
||||
}
|
||||
assets.Serve(w, r, assets.Asset{
|
||||
ContentGz: content,
|
||||
Filename: path,
|
||||
Modified: time.Unix(auto.Generated, 0).UTC(),
|
||||
})
|
||||
}
|
||||
|
||||
func handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
timer := prometheus.NewTimer(apiRequestsSeconds.WithLabelValues(r.Method))
|
||||
|
||||
lw := NewLoggingResponseWriter(w)
|
||||
|
||||
w = NewLoggingResponseWriter(w)
|
||||
defer func() {
|
||||
timer.ObserveDuration()
|
||||
lw := w.(*loggingResponseWriter)
|
||||
apiRequestsTotal.WithLabelValues(r.Method, strconv.Itoa(lw.statusCode)).Inc()
|
||||
}()
|
||||
|
||||
@@ -397,7 +347,7 @@ func handlePostRequest(w http.ResponseWriter, r *http.Request) {
|
||||
if debug {
|
||||
log.Println("Failed to parse payload")
|
||||
}
|
||||
http.Error(w, err.Error(), 500)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -406,7 +356,7 @@ func handlePostRequest(w http.ResponseWriter, r *http.Request) {
|
||||
if debug {
|
||||
log.Println("Failed to parse URI", newRelay.URL)
|
||||
}
|
||||
http.Error(w, err.Error(), 500)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -415,7 +365,7 @@ func handlePostRequest(w http.ResponseWriter, r *http.Request) {
|
||||
if debug {
|
||||
log.Println("Failed to split URI", newRelay.URL)
|
||||
}
|
||||
http.Error(w, err.Error(), 500)
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -491,11 +441,11 @@ func handleRelayTest(request request) {
|
||||
if debug {
|
||||
log.Println("Request for", request.relay)
|
||||
}
|
||||
if !client.TestRelay(context.TODO(), request.relay.uri, []tls.Certificate{testCert}, time.Second, 2*time.Second, 3) {
|
||||
if err := client.TestRelay(context.TODO(), request.relay.uri, []tls.Certificate{testCert}, time.Second, 2*time.Second, 3); err != nil {
|
||||
if debug {
|
||||
log.Println("Test for relay", request.relay, "failed")
|
||||
log.Println("Test for relay", request.relay, "failed:", err)
|
||||
}
|
||||
request.result <- result{errors.New("connection test failed"), 0}
|
||||
request.result <- result{err, 0}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -573,26 +523,21 @@ func evict(relay *relay) func() {
|
||||
}
|
||||
}
|
||||
|
||||
func limit(addr string, cache *lru.Cache, lock sync.RWMutex, intv time.Duration, burst int) bool {
|
||||
func limit(addr string, cache *lru.Cache, lock sync.Mutex, intv time.Duration, burst int) bool {
|
||||
if host, _, err := net.SplitHostPort(addr); err == nil {
|
||||
addr = host
|
||||
}
|
||||
|
||||
lock.RLock()
|
||||
bkt, ok := cache.Get(addr)
|
||||
lock.RUnlock()
|
||||
if ok {
|
||||
bkt := bkt.(*rate.Limiter)
|
||||
if !bkt.Allow() {
|
||||
// Rate limit
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
lock.Lock()
|
||||
cache.Add(addr, rate.NewLimiter(rate.Every(intv), burst))
|
||||
lock.Unlock()
|
||||
lock.Lock()
|
||||
v, _ := cache.Get(addr)
|
||||
bkt, ok := v.(*rate.Limiter)
|
||||
if !ok {
|
||||
bkt = rate.NewLimiter(rate.Every(intv), burst)
|
||||
cache.Add(addr, bkt)
|
||||
}
|
||||
return false
|
||||
lock.Unlock()
|
||||
|
||||
return !bkt.Allow()
|
||||
}
|
||||
|
||||
func loadRelays(file string) []*relay {
|
||||
|
||||
@@ -102,8 +102,9 @@ func main() {
|
||||
showVersion := flag.Bool("version", false, "Show version")
|
||||
flag.Parse()
|
||||
|
||||
longVer := build.LongVersionFor("strelaysrv")
|
||||
if *showVersion {
|
||||
fmt.Println(build.LongVersion)
|
||||
fmt.Println(longVer)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -135,7 +136,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(build.LongVersion)
|
||||
log.Println(longVer)
|
||||
|
||||
maxDescriptors, err := osutil.MaximizeOpenFileLimit()
|
||||
if maxDescriptors > 0 {
|
||||
|
||||
@@ -7,10 +7,15 @@ import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
httpStatusEnhanceYourCalm = 429
|
||||
)
|
||||
|
||||
func poolHandler(pool string, uri *url.URL, mapping mapping) {
|
||||
if debug {
|
||||
log.Println("Joining", pool)
|
||||
@@ -28,38 +33,62 @@ func poolHandler(pool string, uri *url.URL, mapping mapping) {
|
||||
|
||||
resp, err := httpClient.Post(pool, "application/json", &b)
|
||||
if err != nil {
|
||||
log.Println("Error joining pool", pool, err)
|
||||
} else if resp.StatusCode == 500 {
|
||||
bs, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Println("Failed to join", pool, "due to an internal server error. Could not read response:", err)
|
||||
} else {
|
||||
log.Println("Failed to join", pool, "due to an internal server error:", string(bs))
|
||||
}
|
||||
resp.Body.Close()
|
||||
} else if resp.StatusCode == 429 {
|
||||
log.Println(pool, "under load, will retry in a minute")
|
||||
log.Printf("Error joining pool %v: HTTP request: %v", pool, err)
|
||||
time.Sleep(time.Minute)
|
||||
continue
|
||||
} else if resp.StatusCode == 401 {
|
||||
log.Println(pool, "failed to join due to IP address not matching external address. Aborting")
|
||||
return
|
||||
} else if resp.StatusCode == 200 {
|
||||
}
|
||||
|
||||
bs, err := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
log.Printf("Error joining pool %v: reading response: %v", pool, err)
|
||||
time.Sleep(time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
switch resp.StatusCode {
|
||||
case http.StatusOK:
|
||||
var x struct {
|
||||
EvictionIn time.Duration `json:"evictionIn"`
|
||||
}
|
||||
err := json.NewDecoder(resp.Body).Decode(&x)
|
||||
if err == nil {
|
||||
if err := json.NewDecoder(resp.Body).Decode(&x); err == nil {
|
||||
rejoin := x.EvictionIn - (x.EvictionIn / 5)
|
||||
log.Println("Joined", pool, "rejoining in", rejoin)
|
||||
log.Printf("Joined pool %s, rejoining in %v", pool, rejoin)
|
||||
time.Sleep(rejoin)
|
||||
continue
|
||||
} else {
|
||||
log.Println("Failed to deserialize response", err)
|
||||
log.Printf("Joined pool %s, failed to deserialize response: %v", pool, err)
|
||||
}
|
||||
} else {
|
||||
log.Println(pool, "unknown response type from server", resp.StatusCode)
|
||||
|
||||
case http.StatusInternalServerError:
|
||||
log.Printf("Failed to join %v: server error", pool)
|
||||
log.Printf("Response data: %s", bs)
|
||||
time.Sleep(time.Minute)
|
||||
continue
|
||||
|
||||
case http.StatusBadRequest:
|
||||
log.Printf("Failed to join %v: request or check error", pool)
|
||||
log.Printf("Response data: %s", bs)
|
||||
time.Sleep(time.Minute)
|
||||
continue
|
||||
|
||||
case httpStatusEnhanceYourCalm:
|
||||
log.Printf("Failed to join %v: under load (rate limiting)", pool)
|
||||
time.Sleep(time.Minute)
|
||||
continue
|
||||
|
||||
case http.StatusUnauthorized:
|
||||
log.Printf("Failed to join %v: IP address not matching external address", pool)
|
||||
log.Println("Aborting")
|
||||
return
|
||||
|
||||
default:
|
||||
log.Printf("Failed to join %v: unexpected status code from server: %d", pool, resp.StatusCode)
|
||||
log.Printf("Response data: %s", bs)
|
||||
time.Sleep(time.Minute)
|
||||
continue
|
||||
}
|
||||
|
||||
time.Sleep(time.Hour)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,10 +107,10 @@ func main() {
|
||||
connectToStdio(stdin, conn)
|
||||
log.Println("Finished", conn.RemoteAddr(), conn.LocalAddr())
|
||||
} else if test {
|
||||
if client.TestRelay(ctx, uri, []tls.Certificate{cert}, time.Second, 2*time.Second, 4) {
|
||||
if err := client.TestRelay(ctx, uri, []tls.Certificate{cert}, time.Second, 2*time.Second, 4); err == nil {
|
||||
log.Println("OK")
|
||||
} else {
|
||||
log.Println("FAIL")
|
||||
log.Println("FAIL:", err)
|
||||
}
|
||||
} else {
|
||||
log.Fatal("Requires either join or connect")
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/dialer"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
@@ -65,6 +66,12 @@ I.e. to prefix each log line with date and time, set -logflags=3 (1 + 2 from
|
||||
above). The value 0 is used to disable all of the above. The default is to
|
||||
show time only (2).
|
||||
|
||||
Logging always happens to the command line (stdout) and optionally to the
|
||||
file at the path specified by -logfile=path. In addition to an path, the special
|
||||
values "default" and "-" may be used. The former logs to DATADIR/syncthing.log
|
||||
(see -data-dir), which is the default on Windows, and the latter only to stdout,
|
||||
no file, which is the default anywhere else.
|
||||
|
||||
|
||||
Development Settings
|
||||
--------------------
|
||||
@@ -102,10 +109,7 @@ are mostly useful for developers. Use with care.
|
||||
STLOCKTHRESHOLD Used for debugging internal deadlocks; sets debug
|
||||
sensitivity. Use only under direction of a developer.
|
||||
|
||||
STNORESTART Equivalent to the -no-restart argument. Disable the
|
||||
Syncthing monitor process which handles restarts for some
|
||||
configuration changes, upgrades, crashes and also log file
|
||||
writing (stdout is still written).
|
||||
STNORESTART Equivalent to the -no-restart argument.
|
||||
|
||||
STNOUPGRADE Disable automatic upgrades.
|
||||
|
||||
@@ -139,15 +143,27 @@ The following are valid values for the STTRACE variable:
|
||||
%s`
|
||||
)
|
||||
|
||||
// Environment options
|
||||
var (
|
||||
innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != ""
|
||||
// Environment options
|
||||
innerProcess = os.Getenv("STMONITORED") != ""
|
||||
noDefaultFolder = os.Getenv("STNODEFAULTFOLDER") != ""
|
||||
|
||||
upgradeCheckInterval = 5 * time.Minute
|
||||
upgradeRetryInterval = time.Hour
|
||||
upgradeCheckKey = "lastUpgradeCheck"
|
||||
upgradeTimeKey = "lastUpgradeTime"
|
||||
upgradeVersionKey = "lastUpgradeVersion"
|
||||
|
||||
errConcurrentUpgrade = errors.New("upgrade prevented by other running Syncthing instance")
|
||||
errTooEarlyUpgradeCheck = fmt.Errorf("last upgrade check happened less than %v ago, skipping", upgradeCheckInterval)
|
||||
errTooEarlyUpgrade = fmt.Errorf("last upgrade happened less than %v ago, skipping", upgradeRetryInterval)
|
||||
)
|
||||
|
||||
type RuntimeOptions struct {
|
||||
syncthing.Options
|
||||
homeDir string
|
||||
confDir string
|
||||
dataDir string
|
||||
resetDatabase bool
|
||||
showVersion bool
|
||||
showPaths bool
|
||||
@@ -195,11 +211,13 @@ func defaultRuntimeOptions() RuntimeOptions {
|
||||
options.logFlags = logger.DebugFlags
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
// On non-Windows, we explicitly default to "-" which means stdout. On
|
||||
// Windows, the blank options.logFile will later be replaced with the
|
||||
// default path, unless the user has manually specified "-" or
|
||||
// something else.
|
||||
// On non-Windows, we explicitly default to "-" which means stdout. On
|
||||
// Windows, the "default" options.logFile will later be replaced with the
|
||||
// default path, unless the user has manually specified "-" or
|
||||
// something else.
|
||||
if runtime.GOOS == "windows" {
|
||||
options.logFile = "default"
|
||||
} else {
|
||||
options.logFile = "-"
|
||||
}
|
||||
|
||||
@@ -212,11 +230,13 @@ func parseCommandLineOptions() RuntimeOptions {
|
||||
flag.StringVar(&options.generateDir, "generate", "", "Generate key and config in specified dir, then exit")
|
||||
flag.StringVar(&options.guiAddress, "gui-address", options.guiAddress, "Override GUI address (e.g. \"http://192.0.2.42:8443\")")
|
||||
flag.StringVar(&options.guiAPIKey, "gui-apikey", options.guiAPIKey, "Override GUI API key")
|
||||
flag.StringVar(&options.confDir, "home", "", "Set configuration directory")
|
||||
flag.StringVar(&options.homeDir, "home", "", "Set configuration and data directory")
|
||||
flag.StringVar(&options.confDir, "config", "", "Set configuration directory (config and keys)")
|
||||
flag.StringVar(&options.dataDir, "data", "", "Set data directory (database and logs)")
|
||||
flag.IntVar(&options.logFlags, "logflags", options.logFlags, "Select information in log line prefix (see below)")
|
||||
flag.BoolVar(&options.noBrowser, "no-browser", false, "Do not start browser")
|
||||
flag.BoolVar(&options.browserOnly, "browser-only", false, "Open GUI in browser")
|
||||
flag.BoolVar(&options.noRestart, "no-restart", options.noRestart, "Disable monitor process, managed restarts and log file writing")
|
||||
flag.BoolVar(&options.noRestart, "no-restart", options.noRestart, "Do not restart Syncthing when exiting due to API/GUI command, upgrade, or crash")
|
||||
flag.BoolVar(&options.resetDatabase, "reset-database", false, "Reset the database, forcing a full rescan and resync")
|
||||
flag.BoolVar(&options.ResetDeltaIdxs, "reset-deltas", false, "Reset delta index IDs, forcing a full index exchange")
|
||||
flag.BoolVar(&options.doUpgrade, "upgrade", false, "Perform upgrade")
|
||||
@@ -230,7 +250,7 @@ func parseCommandLineOptions() RuntimeOptions {
|
||||
flag.BoolVar(&options.Verbose, "verbose", false, "Print verbose log output")
|
||||
flag.BoolVar(&options.paused, "paused", false, "Start with all devices and folders paused")
|
||||
flag.BoolVar(&options.unpaused, "unpaused", false, "Start with all devices and folders unpaused")
|
||||
flag.StringVar(&options.logFile, "logfile", options.logFile, "Log file name (still always logs to stdout).")
|
||||
flag.StringVar(&options.logFile, "logfile", options.logFile, "Log file name (see below).")
|
||||
flag.IntVar(&options.logMaxSize, "log-max-size", options.logMaxSize, "Maximum size of any file (zero to disable log rotation).")
|
||||
flag.IntVar(&options.logMaxFiles, "log-max-old-files", options.logMaxFiles, "Number of old files to keep (zero to keep only current).")
|
||||
flag.StringVar(&options.auditFile, "auditfile", options.auditFile, "Specify audit file (use \"-\" for stdout, \"--\" for stderr)")
|
||||
@@ -252,6 +272,17 @@ func parseCommandLineOptions() RuntimeOptions {
|
||||
return options
|
||||
}
|
||||
|
||||
func setLocation(enum locations.BaseDirEnum, loc string) error {
|
||||
if !filepath.IsAbs(loc) {
|
||||
var err error
|
||||
loc, err = filepath.Abs(loc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return locations.SetBaseDir(enum, loc)
|
||||
}
|
||||
|
||||
func main() {
|
||||
options := parseCommandLineOptions()
|
||||
l.SetFlags(options.logFlags)
|
||||
@@ -269,25 +300,33 @@ func main() {
|
||||
osutil.HideConsole()
|
||||
}
|
||||
|
||||
if options.confDir != "" {
|
||||
// Not set as default above because the string can be really long.
|
||||
if !filepath.IsAbs(options.confDir) {
|
||||
var err error
|
||||
options.confDir, err = filepath.Abs(options.confDir)
|
||||
if err != nil {
|
||||
l.Warnln("Failed to make options path absolute:", err)
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
}
|
||||
// Not set as default above because the strings can be really long.
|
||||
var err error
|
||||
homeSet := options.homeDir != ""
|
||||
confSet := options.confDir != ""
|
||||
dataSet := options.dataDir != ""
|
||||
switch {
|
||||
case dataSet != confSet:
|
||||
err = errors.New("either both or none of -conf and -data must be given, use -home to set both at once")
|
||||
case homeSet && dataSet:
|
||||
err = errors.New("-home must not be used together with -conf and -data")
|
||||
case homeSet:
|
||||
if err = setLocation(locations.ConfigBaseDir, options.homeDir); err == nil {
|
||||
err = setLocation(locations.DataBaseDir, options.homeDir)
|
||||
}
|
||||
if err := locations.SetBaseDir(locations.ConfigBaseDir, options.confDir); err != nil {
|
||||
l.Warnln(err)
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
case dataSet:
|
||||
if err = setLocation(locations.ConfigBaseDir, options.confDir); err == nil {
|
||||
err = setLocation(locations.DataBaseDir, options.dataDir)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
l.Warnln("Command line options:", err)
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
}
|
||||
|
||||
if options.logFile == "" {
|
||||
// Blank means use the default logfile location. We must set this
|
||||
// *after* expandLocations above.
|
||||
if options.logFile == "default" || options.logFile == "" {
|
||||
// We must set this *after* expandLocations above.
|
||||
// Handling an empty value is for backwards compatibility (<1.4.1).
|
||||
options.logFile = locations.Get(locations.LogFile)
|
||||
}
|
||||
|
||||
@@ -359,14 +398,31 @@ func main() {
|
||||
}
|
||||
|
||||
if options.doUpgradeCheck {
|
||||
checkUpgrade()
|
||||
if _, err := checkUpgrade(); err != nil {
|
||||
l.Warnln("Checking for upgrade:", err)
|
||||
os.Exit(exitCodeForUpgrade(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if options.doUpgrade {
|
||||
release := checkUpgrade()
|
||||
performUpgrade(release)
|
||||
return
|
||||
release, err := checkUpgrade()
|
||||
if err == nil {
|
||||
// Use leveldb database locks to protect against concurrent upgrades
|
||||
ldb, err := syncthing.OpenDBBackend(locations.Get(locations.Database), config.TuningAuto)
|
||||
if err != nil {
|
||||
err = upgradeViaRest()
|
||||
} else {
|
||||
_ = ldb.Close()
|
||||
err = upgrade.To(release)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
l.Warnln("Upgrade:", err)
|
||||
os.Exit(exitCodeForUpgrade(err))
|
||||
}
|
||||
l.Infof("Upgraded to %q", release.Tag)
|
||||
os.Exit(syncthing.ExitUpgrade.AsInt())
|
||||
}
|
||||
|
||||
if options.resetDatabase {
|
||||
@@ -462,45 +518,28 @@ func debugFacilities() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func checkUpgrade() upgrade.Release {
|
||||
type errNoUpgrade struct {
|
||||
current, latest string
|
||||
}
|
||||
|
||||
func (e errNoUpgrade) Error() string {
|
||||
return fmt.Sprintf("no upgrade available (current %q >= latest %q).", e.current, e.latest)
|
||||
}
|
||||
|
||||
func checkUpgrade() (upgrade.Release, error) {
|
||||
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger)
|
||||
opts := cfg.Options()
|
||||
release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
|
||||
if err != nil {
|
||||
l.Warnln("Upgrade:", err)
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
return upgrade.Release{}, err
|
||||
}
|
||||
|
||||
if upgrade.CompareVersions(release.Tag, build.Version) <= 0 {
|
||||
noUpgradeMessage := "No upgrade available (current %q >= latest %q)."
|
||||
l.Infof(noUpgradeMessage, build.Version, release.Tag)
|
||||
os.Exit(syncthing.ExitNoUpgradeAvailable.AsInt())
|
||||
return upgrade.Release{}, errNoUpgrade{build.Version, release.Tag}
|
||||
}
|
||||
|
||||
l.Infof("Upgrade available (current %q < latest %q)", build.Version, release.Tag)
|
||||
return release
|
||||
}
|
||||
|
||||
func performUpgrade(release upgrade.Release) {
|
||||
// Use leveldb database locks to protect against concurrent upgrades
|
||||
_, err := syncthing.OpenDBBackend(locations.Get(locations.Database), config.TuningAuto)
|
||||
if err == nil {
|
||||
err = upgrade.To(release)
|
||||
if err != nil {
|
||||
l.Warnln("Upgrade:", err)
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
}
|
||||
l.Infof("Upgraded to %q", release.Tag)
|
||||
} else {
|
||||
l.Infoln("Attempting upgrade through running Syncthing...")
|
||||
err = upgradeViaRest()
|
||||
if err != nil {
|
||||
l.Warnln("Upgrade:", err)
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
}
|
||||
l.Infoln("Syncthing upgrading")
|
||||
os.Exit(syncthing.ExitUpgrade.AsInt())
|
||||
}
|
||||
return release, nil
|
||||
}
|
||||
|
||||
func upgradeViaRest() error {
|
||||
@@ -568,10 +607,21 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
}
|
||||
|
||||
if runtimeOptions.unpaused {
|
||||
setPauseState(cfg, false)
|
||||
} else if runtimeOptions.paused {
|
||||
setPauseState(cfg, true)
|
||||
// Candidate builds should auto upgrade. Make sure the option is set,
|
||||
// unless we are in a build where it's disabled or the STNOUPGRADE
|
||||
// environment variable is set.
|
||||
|
||||
if build.IsCandidate && !upgrade.DisabledByCompilation && !runtimeOptions.NoUpgrade {
|
||||
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
|
||||
if opts := cfg.Options(); opts.AutoUpgradeIntervalH == 0 || opts.AutoUpgradeIntervalH > 24 {
|
||||
opts.AutoUpgradeIntervalH = 12
|
||||
// Set the option into the config as well, as the auto upgrade
|
||||
// loop expects to read a valid interval from there.
|
||||
cfg.SetOptions(opts)
|
||||
cfg.Save()
|
||||
}
|
||||
// We don't tweak the user's choice of upgrading to pre-releases or
|
||||
// not, as otherwise they cannot step off the candidate channel.
|
||||
}
|
||||
|
||||
dbFile := locations.Get(locations.Database)
|
||||
@@ -581,6 +631,35 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Check if auto-upgrades should be done and if yes, do an initial
|
||||
// upgrade immedately. The auto-upgrade routine can only be started
|
||||
// later after App is initialised.
|
||||
|
||||
shouldAutoUpgrade := shouldUpgrade(cfg, runtimeOptions)
|
||||
if shouldAutoUpgrade {
|
||||
// try to do upgrade directly and log the error if relevant.
|
||||
release, err := initialAutoUpgradeCheck(db.NewMiscDataNamespace(ldb))
|
||||
if err == nil {
|
||||
err = upgrade.To(release)
|
||||
}
|
||||
if err != nil {
|
||||
if _, ok := err.(errNoUpgrade); ok || err == errTooEarlyUpgradeCheck || err == errTooEarlyUpgrade {
|
||||
l.Debugln("Initial automatic upgrade:", err)
|
||||
} else {
|
||||
l.Infoln("Initial automatic upgrade:", err)
|
||||
}
|
||||
} else {
|
||||
l.Infof("Upgraded to %q, exiting now.", release.Tag)
|
||||
os.Exit(syncthing.ExitUpgrade.AsInt())
|
||||
}
|
||||
}
|
||||
|
||||
if runtimeOptions.unpaused {
|
||||
setPauseState(cfg, false)
|
||||
} else if runtimeOptions.paused {
|
||||
setPauseState(cfg, true)
|
||||
}
|
||||
|
||||
appOpts := runtimeOptions.Options
|
||||
if runtimeOptions.auditEnabled {
|
||||
appOpts.AuditWriter = auditWriter(runtimeOptions.auditFile)
|
||||
@@ -589,9 +668,19 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
secs, _ := strconv.Atoi(t)
|
||||
appOpts.DeadlockTimeoutS = secs
|
||||
}
|
||||
if dur, err := time.ParseDuration(os.Getenv("STRECHECKDBEVERY")); err == nil {
|
||||
appOpts.DBRecheckInterval = dur
|
||||
}
|
||||
if dur, err := time.ParseDuration(os.Getenv("STGCINDIRECTEVERY")); err == nil {
|
||||
appOpts.DBIndirectGCInterval = dur
|
||||
}
|
||||
|
||||
app := syncthing.New(cfg, ldb, evLogger, cert, appOpts)
|
||||
|
||||
if shouldAutoUpgrade {
|
||||
go autoUpgrade(cfg, app, evLogger)
|
||||
}
|
||||
|
||||
setupSignalHandling(app)
|
||||
|
||||
if len(os.Getenv("GOMAXPROCS")) == 0 {
|
||||
@@ -614,31 +703,6 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
go standbyMonitor(app)
|
||||
}
|
||||
|
||||
// Candidate builds should auto upgrade. Make sure the option is set,
|
||||
// unless we are in a build where it's disabled or the STNOUPGRADE
|
||||
// environment variable is set.
|
||||
|
||||
if build.IsCandidate && !upgrade.DisabledByCompilation && !runtimeOptions.NoUpgrade {
|
||||
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
|
||||
if opts := cfg.Options(); opts.AutoUpgradeIntervalH == 0 || opts.AutoUpgradeIntervalH > 24 {
|
||||
opts.AutoUpgradeIntervalH = 12
|
||||
// Set the option into the config as well, as the auto upgrade
|
||||
// loop expects to read a valid interval from there.
|
||||
cfg.SetOptions(opts)
|
||||
cfg.Save()
|
||||
}
|
||||
// We don't tweak the user's choice of upgrading to pre-releases or
|
||||
// not, as otherwise they cannot step off the candidate channel.
|
||||
}
|
||||
|
||||
if opts := cfg.Options(); opts.AutoUpgradeIntervalH > 0 {
|
||||
if runtimeOptions.NoUpgrade {
|
||||
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
|
||||
} else {
|
||||
go autoUpgrade(cfg, app, evLogger)
|
||||
}
|
||||
}
|
||||
|
||||
if err := app.Start(); err != nil {
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
}
|
||||
@@ -771,8 +835,22 @@ func standbyMonitor(app *syncthing.App) {
|
||||
}
|
||||
}
|
||||
|
||||
func shouldUpgrade(cfg config.Wrapper, runtimeOptions RuntimeOptions) bool {
|
||||
if upgrade.DisabledByCompilation {
|
||||
return false
|
||||
}
|
||||
if opts := cfg.Options(); opts.AutoUpgradeIntervalH < 0 {
|
||||
return false
|
||||
}
|
||||
if runtimeOptions.NoUpgrade {
|
||||
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger) {
|
||||
timer := time.NewTimer(0)
|
||||
timer := time.NewTimer(upgradeCheckInterval)
|
||||
sub := evLogger.Subscribe(events.DeviceConnected)
|
||||
for {
|
||||
select {
|
||||
@@ -827,6 +905,26 @@ func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger)
|
||||
}
|
||||
}
|
||||
|
||||
func initialAutoUpgradeCheck(misc *db.NamespacedKV) (upgrade.Release, error) {
|
||||
if last, ok, err := misc.Time(upgradeCheckKey); err == nil && ok && time.Since(last) < upgradeCheckInterval {
|
||||
return upgrade.Release{}, errTooEarlyUpgradeCheck
|
||||
}
|
||||
_ = misc.PutTime(upgradeCheckKey, time.Now())
|
||||
release, err := checkUpgrade()
|
||||
if err != nil {
|
||||
return upgrade.Release{}, err
|
||||
}
|
||||
if lastVersion, ok, err := misc.String(upgradeVersionKey); err == nil && ok && lastVersion == release.Tag {
|
||||
// Only check time if we try to upgrade to the same release.
|
||||
if lastTime, ok, err := misc.Time(upgradeTimeKey); err == nil && ok && time.Since(lastTime) < upgradeRetryInterval {
|
||||
return upgrade.Release{}, errTooEarlyUpgrade
|
||||
}
|
||||
}
|
||||
_ = misc.PutString(upgradeVersionKey, release.Tag)
|
||||
_ = misc.PutTime(upgradeTimeKey, time.Now())
|
||||
return release, nil
|
||||
}
|
||||
|
||||
// cleanConfigDirectory removes old, unused configuration and index formats, a
|
||||
// suitable time after they have gone out of fashion.
|
||||
func cleanConfigDirectory() {
|
||||
@@ -893,3 +991,10 @@ func setPauseState(cfg config.Wrapper, paused bool) {
|
||||
os.Exit(syncthing.ExitError.AsInt())
|
||||
}
|
||||
}
|
||||
|
||||
func exitCodeForUpgrade(err error) int {
|
||||
if _, ok := err.(errNoUpgrade); ok {
|
||||
return syncthing.ExitNoUpgradeAvailable.AsInt()
|
||||
}
|
||||
return syncthing.ExitError.AsInt()
|
||||
}
|
||||
|
||||
@@ -311,6 +311,11 @@ func copyStdout(stdout io.Reader, dst io.Writer) {
|
||||
}
|
||||
|
||||
func restartMonitor(args []string) error {
|
||||
// Set the STRESTART environment variable to indicate to the next
|
||||
// process that this is a restart and not initial start. This prevents
|
||||
// opening the browser on startup.
|
||||
os.Setenv("STRESTART", "yes")
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
// syscall.Exec is the cleanest way to restart on Unixes as it
|
||||
// replaces the current process with the new one, keeping the pid and
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -754,6 +755,7 @@ func main() {
|
||||
http.HandleFunc("/movement.json", withDB(db, movementHandler))
|
||||
http.HandleFunc("/performance.json", withDB(db, performanceHandler))
|
||||
http.HandleFunc("/blockstats.json", withDB(db, blockStatsHandler))
|
||||
http.HandleFunc("/locations.json", withDB(db, locationsHandler))
|
||||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||||
|
||||
go cacheRefresher(db)
|
||||
@@ -765,9 +767,10 @@ func main() {
|
||||
}
|
||||
|
||||
var (
|
||||
cacheData []byte
|
||||
cacheTime time.Time
|
||||
cacheMut sync.Mutex
|
||||
cachedIndex []byte
|
||||
cachedLocations []byte
|
||||
cacheTime time.Time
|
||||
cacheMut sync.Mutex
|
||||
)
|
||||
|
||||
const maxCacheTime = 15 * time.Minute
|
||||
@@ -791,8 +794,15 @@ func refreshCacheLocked(db *sql.DB) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cacheData = buf.Bytes()
|
||||
cachedIndex = buf.Bytes()
|
||||
cacheTime = time.Now()
|
||||
|
||||
locs := rep["locations"].(map[location]int)
|
||||
wlocs := make([]weightedLocation, 0, len(locs))
|
||||
for loc, w := range locs {
|
||||
wlocs = append(wlocs, weightedLocation{loc, w})
|
||||
}
|
||||
cachedLocations, _ = json.Marshal(wlocs)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -810,13 +820,29 @@ func rootHandler(db *sql.DB, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Write(cacheData)
|
||||
w.Write(cachedIndex)
|
||||
} else {
|
||||
http.Error(w, "Not found", 404)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func locationsHandler(db *sql.DB, w http.ResponseWriter, r *http.Request) {
|
||||
cacheMut.Lock()
|
||||
defer cacheMut.Unlock()
|
||||
|
||||
if time.Since(cacheTime) > maxCacheTime {
|
||||
if err := refreshCacheLocked(db); err != nil {
|
||||
log.Println(err)
|
||||
http.Error(w, "Template Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.Write(cachedLocations)
|
||||
}
|
||||
|
||||
func newDataHandler(db *sql.DB, w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
|
||||
@@ -875,7 +901,8 @@ func newDataHandler(db *sql.DB, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func summaryHandler(db *sql.DB, w http.ResponseWriter, r *http.Request) {
|
||||
s, err := getSummary(db)
|
||||
min, _ := strconv.Atoi(r.URL.Query().Get("min"))
|
||||
s, err := getSummary(db, min)
|
||||
if err != nil {
|
||||
log.Println("summaryHandler:", err)
|
||||
http.Error(w, "Database Error", http.StatusInternalServerError)
|
||||
@@ -1016,8 +1043,13 @@ func inc(storage map[string]int, key string, i interface{}) {
|
||||
}
|
||||
|
||||
type location struct {
|
||||
Latitude float64
|
||||
Longitude float64
|
||||
Latitude float64 `json:"lat"`
|
||||
Longitude float64 `json:"lon"`
|
||||
}
|
||||
|
||||
type weightedLocation struct {
|
||||
location
|
||||
Weight int `json:"weight"`
|
||||
}
|
||||
|
||||
func getReport(db *sql.DB) map[string]interface{} {
|
||||
@@ -1528,7 +1560,21 @@ func (s *summary) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(table)
|
||||
}
|
||||
|
||||
func getSummary(db *sql.DB) (summary, error) {
|
||||
// filter removes versions that never reach the specified min count.
|
||||
func (s *summary) filter(min int) {
|
||||
// We cheat and just remove the versions from the "index" and leave the
|
||||
// data points alone. The version index is used to build the table when
|
||||
// we do the serialization, so at that point the data points are
|
||||
// filtered out as well.
|
||||
for ver := range s.versions {
|
||||
if s.max[ver] < min {
|
||||
delete(s.versions, ver)
|
||||
delete(s.max, ver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getSummary(db *sql.DB, min int) (summary, error) {
|
||||
s := newSummary()
|
||||
|
||||
rows, err := db.Query(`SELECT Day, Version, Count FROM VersionSummary WHERE Day > now() - '2 year'::INTERVAL;`)
|
||||
@@ -1559,6 +1605,7 @@ func getSummary(db *sql.DB) (summary, error) {
|
||||
s.setCount(day.Format("2006-01-02"), ver, num)
|
||||
}
|
||||
|
||||
s.filter(min)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,11 @@ found in the LICENSE file.
|
||||
<link href="static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="static/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=visualization&key=AIzaSyDk5WJ8s7ueLKb99X5DbQ-vkWtPDAKqYs0"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/heatmapjs@2.0.2/heatmap.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/leaflet-heatmap@1.0.0/leaflet-heatmap.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 40px;
|
||||
@@ -49,10 +53,12 @@ found in the LICENSE file.
|
||||
google.setOnLoadCallback(drawMovementChart);
|
||||
google.setOnLoadCallback(drawBlockStatsChart);
|
||||
google.setOnLoadCallback(drawPerformanceCharts);
|
||||
google.setOnLoadCallback(drawHeatMap);
|
||||
|
||||
function drawVersionChart() {
|
||||
var jsonData = $.ajax({url: "summary.json", dataType:"json", async: false}).responseText;
|
||||
// Summary version chart for versions that at some point in the chart
|
||||
// reaches 250 devices. This filters out versions that are old and
|
||||
// uninteresting yet linger forever with like four users.
|
||||
var jsonData = $.ajax({url: "summary.json?min=250", dataType:"json", async: false}).responseText;
|
||||
var rows = JSON.parse(jsonData);
|
||||
|
||||
var data = new google.visualization.DataTable();
|
||||
@@ -211,47 +217,46 @@ found in the LICENSE file.
|
||||
|
||||
var locations = [];
|
||||
{{range $location, $weight := .locations}}
|
||||
locations.push({location: new google.maps.LatLng({{- $location.Latitude -}}, {{- $location.Longitude -}}), weight: {{- $weight -}}});
|
||||
locations.push({lat:{{- $location.Latitude -}},lng:{{- $location.Longitude -}},count:Math.min(100, {{- $weight -}})});
|
||||
{{- end}}
|
||||
|
||||
function drawHeatMap() {
|
||||
if (locations.length == 0) {
|
||||
return;
|
||||
}
|
||||
var mapBounds = new google.maps.LatLngBounds();
|
||||
var map = new google.maps.Map(document.getElementById('map'), {
|
||||
zoom: 1,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
});
|
||||
var heatmap = new google.maps.visualization.HeatmapLayer({
|
||||
var testData = {
|
||||
data: locations
|
||||
};
|
||||
|
||||
var baseLayer = L.tileLayer(
|
||||
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
|
||||
attribution: '...',
|
||||
maxZoom: 18
|
||||
}
|
||||
);
|
||||
var cfg = {
|
||||
"radius": 1,
|
||||
"minOpacity": .25,
|
||||
"maxOpacity": .8,
|
||||
"scaleRadius": true,
|
||||
"useLocalExtrema": true,
|
||||
latField: 'lat',
|
||||
lngField: 'lng',
|
||||
valueField: 'count',
|
||||
gradient: {
|
||||
'.1': 'cyan',
|
||||
'.8': 'blue',
|
||||
'.95': 'red'
|
||||
}
|
||||
};
|
||||
var heatmapLayer = new HeatmapOverlay(cfg);
|
||||
|
||||
var map = new L.Map('map', {
|
||||
center: new L.LatLng(25, 0),
|
||||
zoom: 1,
|
||||
layers: [baseLayer, heatmapLayer]
|
||||
});
|
||||
heatmap.set('radius', 10);
|
||||
heatmap.set('maxIntensity', 20);
|
||||
heatmap.set('gradient', [
|
||||
'rgba(0, 255, 255, 0)',
|
||||
'rgba(0, 255, 255, 1)',
|
||||
'rgba(0, 191, 255, 1)',
|
||||
'rgba(0, 127, 255, 1)',
|
||||
'rgba(0, 63, 255, 1)',
|
||||
'rgba(0, 0, 255, 1)',
|
||||
'rgba(0, 0, 223, 1)',
|
||||
'rgba(0, 0, 191, 1)',
|
||||
'rgba(0, 0, 159, 1)',
|
||||
'rgba(0, 0, 127, 1)',
|
||||
'rgba(63, 0, 91, 1)',
|
||||
'rgba(127, 0, 63, 1)',
|
||||
'rgba(191, 0, 31, 1)',
|
||||
'rgba(255, 0, 0, 1)'
|
||||
]);
|
||||
heatmap.setMap(map);
|
||||
for (var x = 0; x < locations.length; x++) {
|
||||
mapBounds.extend(locations[x].location);
|
||||
}
|
||||
map.fitBounds(mapBounds);
|
||||
if (locations.length == 1) {
|
||||
map.setZoom(13);
|
||||
}
|
||||
heatmapLayer.setData(testData);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
@@ -296,7 +301,7 @@ found in the LICENSE file.
|
||||
{{if .locations}}
|
||||
<div class="img-thumbnail" id="map" style="width: 1130px; height: 400px; padding: 10px;"></div>
|
||||
<p class="text-muted">
|
||||
Heatmap max intensity is capped at 20 reports within a location.
|
||||
Heatmap max intensity is capped at 100 reports within a location.
|
||||
</p>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
@@ -651,6 +656,7 @@ found in the LICENSE file.
|
||||
</p>
|
||||
<script type="text/javascript">
|
||||
$('[data-toggle="tooltip"]').tooltip({html:true});
|
||||
drawHeatMap();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Name=Start Syncthing
|
||||
GenericName=File synchronization
|
||||
Comment=Starts the main syncthing process in the background.
|
||||
Exec=/usr/bin/syncthing -no-browser -logfile=~/.config/syncthing/syncthing.log
|
||||
Exec=/usr/bin/syncthing -no-browser -logfile=default
|
||||
Icon=syncthing
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
||||
23
go.mod
23
go.mod
@@ -12,22 +12,22 @@ require (
|
||||
github.com/d4l3k/messagediff v1.2.1
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
|
||||
github.com/getsentry/raven-go v0.2.0
|
||||
github.com/go-ldap/ldap/v3 v3.1.10
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogo/protobuf v1.3.1
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6
|
||||
github.com/golang/mock v1.3.1 // indirect
|
||||
github.com/jackpal/gateway v1.0.5
|
||||
github.com/golang/protobuf v1.4.0 // indirect
|
||||
github.com/greatroar/blobloom v0.2.1
|
||||
github.com/jackpal/gateway v1.0.6
|
||||
github.com/jackpal/go-nat-pmp v1.0.2
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/kr/pretty v0.2.0 // indirect
|
||||
github.com/lib/pq v1.2.0
|
||||
github.com/lucas-clemente/quic-go v0.12.1
|
||||
github.com/lucas-clemente/quic-go v0.15.7
|
||||
github.com/maruel/panicparse v1.3.0
|
||||
github.com/mattn/go-isatty v0.0.11
|
||||
github.com/minio/sha256-simd v0.1.1
|
||||
github.com/onsi/ginkgo v1.9.0 // indirect
|
||||
github.com/onsi/gomega v1.6.0 // indirect
|
||||
github.com/oschwald/geoip2-golang v1.4.0
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
@@ -35,24 +35,17 @@ require (
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563
|
||||
github.com/sasha-s/go-deadlock v0.2.0
|
||||
github.com/shirou/gopsutil v0.0.0-20190714054239-47ef3260b6bf
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d
|
||||
github.com/thejerf/suture v3.0.2+incompatible
|
||||
github.com/urfave/cli v1.22.2
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
|
||||
github.com/willf/bitset v1.1.10 // indirect
|
||||
github.com/willf/bloom v2.0.3+incompatible
|
||||
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472
|
||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
|
||||
golang.org/x/text v0.3.2
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
gopkg.in/ldap.v2 v2.5.1
|
||||
)
|
||||
|
||||
go 1.13
|
||||
|
||||
// https://github.com/spaolacci/murmur3/pull/30
|
||||
replace github.com/spaolacci/murmur3 v1.1.0 => github.com/calmh/murmur3 v1.1.1-0.20200226160057-74e9af8f47ac
|
||||
|
||||
222
go.sum
222
go.sum
@@ -1,3 +1,12 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20190627213056-c55ef6137fc6 h1:Apvc4kyfdrOxG+F5dn8osz+45kwGJa6CySQn0tB38SU=
|
||||
github.com/AudriusButkevicius/pfilter v0.0.0-20190627213056-c55ef6137fc6/go.mod h1:1N0EEx/irz4B1qV17wW82TFbjQrE7oX316Cki6eDY0Q=
|
||||
github.com/AudriusButkevicius/recli v0.0.5 h1:xUa55PvWTHBm17T6RvjElRO3y5tALpdceH86vhzQ5wg=
|
||||
@@ -7,12 +16,15 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIO
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75 h1:3ILjVyslFbc4jl1w5TWuvvslFD/nDfR2H8tVaMVLrEY=
|
||||
github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
@@ -21,8 +33,9 @@ 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/bkaradzic/go-lz4 v0.0.0-20160924222819-7224d8d8f27e h1:2augTYh6E+XoNrrivZJBadpThP/dsvYKj0nzqfQ8tM4=
|
||||
github.com/bkaradzic/go-lz4 v0.0.0-20160924222819-7224d8d8f27e/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||
github.com/calmh/murmur3 v1.1.1-0.20200226160057-74e9af8f47ac h1:mc24tiVsBenJuhJFQzgvTo1ECJxCGXUgNktcfEhJHHo=
|
||||
github.com/calmh/murmur3 v1.1.1-0.20200226160057-74e9af8f47ac/go.mod h1:nZyyz8Qrw2g3CakiZkVTsiwKlCgQSCf2ZCAFB3DHbaI=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625 h1:ckJgFhFWywOx+YLEMIJsTb+NV6NexWICk5+AMSuz3ss=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/calmh/xdr v1.1.0 h1:U/Dd4CXNLoo8EiQ4ulJUXkgO1/EyQLgDKLgpY1SOoJE=
|
||||
github.com/calmh/xdr v1.1.0/go.mod h1:E8sz2ByAdXC8MbANf1LCRYzedSnnc+/sXXJs/PVqoeg=
|
||||
github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d h1:As4937T5NVbJ/DmZT9z33pyLEprMd6CUSfhbmMY57Io=
|
||||
@@ -35,6 +48,8 @@ github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitf
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/chmduquesne/rollinghash v0.0.0-20180912150627-a60f8e7142b5 h1:Wg96Dh0MLTanEaPO0OkGtUIaa2jOnShAIOVUIzRHUxo=
|
||||
github.com/chmduquesne/rollinghash v0.0.0-20180912150627-a60f8e7142b5/go.mod h1:Uc2I36RRfTAf7Dge82bi3RU0OQUmXT9iweIcPqvr8A0=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
|
||||
@@ -42,14 +57,27 @@ github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkE
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI=
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
|
||||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1 h1:gvPdv/Hr++TRFCl0UbPFHC54P9N9jgsRPnmnr419Uck=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-ldap/ldap/v3 v3.1.7 h1:aHjuWTgZsnxjMgqzx0JHwNqz4jBYZTcNarbPFkW1Oww=
|
||||
github.com/go-ldap/ldap/v3 v3.1.7/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
|
||||
github.com/go-ldap/ldap/v3 v3.1.10 h1:7WsKqasmPThNvdl0Q5GPpbTDD/ZD98CfuawrMIuh7qQ=
|
||||
github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||
@@ -62,32 +90,58 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0 h1:Rd1kQnQu0Hq3qvJppYSG0HtP+f5LPPUiDswTLiEegLg=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/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 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/greatroar/blobloom v0.2.1 h1:Ie7+kTQFhcvfFHhzOYSJA2XE5sp8c9iB5iapu2tIig4=
|
||||
github.com/greatroar/blobloom v0.2.1/go.mod h1:we9vO6GNYMmsNvCWINtZnQbcGEHUT6hGBAznNHd6RlE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc=
|
||||
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
|
||||
github.com/jackpal/gateway v1.0.6 h1:/MJORKvJEwNVldtGVJC2p2cwCnsSoLn3hl3zxmZT7tk=
|
||||
github.com/jackpal/gateway v1.0.6/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
@@ -95,18 +149,24 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lucas-clemente/quic-go v0.12.1 h1:BPITli+6KnKogtTxBk2aS4okr5dUHz2LtIDAP1b8UL4=
|
||||
github.com/lucas-clemente/quic-go v0.12.1/go.mod h1:UXJJPE4RfFef/xPO5wQm0tITK8gNfqwTxjbE7s3Vb8s=
|
||||
github.com/lucas-clemente/quic-go v0.15.6 h1:2l7g4fjjjwqmM3NirLiBtszMaR7aDTSsiiXY9FrGroo=
|
||||
github.com/lucas-clemente/quic-go v0.15.6/go.mod h1:Myi1OyS0FOjL3not4BxT7KN29bRkcMUV5JVVFLKtDp8=
|
||||
github.com/lucas-clemente/quic-go v0.15.7 h1:Pu7To5/G9JoP1mwlrcIvfV8ByPBlCzif3MCl8+1W83I=
|
||||
github.com/lucas-clemente/quic-go v0.15.7/go.mod h1:Myi1OyS0FOjL3not4BxT7KN29bRkcMUV5JVVFLKtDp8=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
|
||||
github.com/marten-seemann/qtls v0.3.2 h1:O7awy4bHEzSX/K3h+fZig3/Vo03s/RxlxgsAk9sYamI=
|
||||
github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
|
||||
github.com/marten-seemann/qtls v0.9.1 h1:O0YKQxNVPaiFgMng0suWEOY2Sb4LT2sRn9Qimq3Z1IQ=
|
||||
github.com/marten-seemann/qtls v0.9.1/go.mod h1:T1MmAdDPyISzxlK6kjRr0pcZFBVd1OZbBb/j3cvzHhk=
|
||||
github.com/maruel/panicparse v1.3.0 h1:1Ep/RaYoSL1r5rTILHQQbyzHG8T4UP5ZbQTYTo4bdDc=
|
||||
github.com/maruel/panicparse v1.3.0/go.mod h1:vszMjr5QQ4F5FSRfraldcIA/BCw5xrdLL+zEcU2nRBs=
|
||||
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
||||
@@ -120,6 +180,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -127,15 +188,18 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.9.0 h1:SZjF721BByVj8QH636/8S2DnX4n0Re3SteMmw3N+tzc=
|
||||
github.com/onsi/ginkgo v1.9.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.6.0 h1:8XTW0fcJZEq9q+Upcyws4JSGua2MFysCL5xkaSgHc+M=
|
||||
github.com/onsi/gomega v1.6.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
|
||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/oschwald/geoip2-golang v1.4.0 h1:5RlrjCgRyIGDz/mBmPfnAF4h8k0IAcRv9PvrpOfz+Ug=
|
||||
github.com/oschwald/geoip2-golang v1.4.0/go.mod h1:8QwxJvRImBH+Zl6Aa6MaIcs5YdlZSTKtzmPGzQqi9ng=
|
||||
github.com/oschwald/maxminddb-golang v1.6.0 h1:KAJSjdHQ8Kv45nFIbtoLGrGWqHFajOIm7skTyz/+Dls=
|
||||
@@ -145,12 +209,11 @@ github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCr
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.0 h1:J8lpUdobwIeCI7OiSxHqEwJUKvJwicL5+3v1oe2Yb4k=
|
||||
github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
|
||||
@@ -161,10 +224,12 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
@@ -172,20 +237,45 @@ github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQl
|
||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=
|
||||
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil v0.0.0-20190714054239-47ef3260b6bf h1:c9SV5NzG4KOk448TUE7iqCmb4E4y79CZF4zDdc1Jx3Q=
|
||||
github.com/shirou/gopsutil v0.0.0-20190714054239-47ef3260b6bf/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
||||
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
|
||||
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
|
||||
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
|
||||
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
|
||||
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
|
||||
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
|
||||
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
|
||||
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
|
||||
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
|
||||
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
||||
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
@@ -194,51 +284,76 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2 h1:6tuEEEpg+mxM82E0YingzoXzXXISYR/o/7I9n573LWI=
|
||||
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2/go.mod h1:Sn4ChoS7e4FxjCN1XHPVBT43AgnRLbuaB8pEc1Zcdjg=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/thejerf/suture v3.0.2+incompatible h1:GtMydYcnK4zBJ0KL6Lx9vLzl6Oozb65wh252FTBxrvM=
|
||||
github.com/thejerf/suture v3.0.2+incompatible/go.mod h1:ibKwrVj+Uzf3XZdAiNWUouPaAbSoemxOHLmJmwheEMc=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
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/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bloom v2.0.3+incompatible h1:QDacWdqcAUI1MPOwIQZRy9kOR7yxfyEmxX8Wdm2/JPA=
|
||||
github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
|
||||
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU=
|
||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c=
|
||||
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
|
||||
@@ -247,30 +362,71 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191224085550-c709ea063b76 h1:Dho5nD6R3PcW2SH1or8vS0dszDaXRxIw55lBX7XiE5g=
|
||||
golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU=
|
||||
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
|
||||
@@ -136,6 +136,11 @@ table.table-auto td {
|
||||
max-width: 0px;
|
||||
}
|
||||
|
||||
/* Wrap long file paths to prevent text overflow. See issue #6268. */
|
||||
.file-path {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.folder-advanced {
|
||||
padding: 1rem;
|
||||
margin-bottom: 15px;
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Коментар, използван в началото на реда",
|
||||
"Compression": "Компресиране",
|
||||
"Configured": "Настроен",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Грешка при свързването",
|
||||
"Connection Type": "Вид връзка",
|
||||
"Connections": "Връзки",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Периодичните сканирания са деактивирани и задаването на наблюдение за промени е неуспешно, ще опита пак след 1мин:",
|
||||
"Discard": "Discard",
|
||||
"Disconnected": "Не е свързано",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Открит",
|
||||
"Discovery": "Откриване",
|
||||
"Discovery Failures": "Грешка в откриването",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Може да предлага други устройства",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Обратното на даденото условие (пр. не изключвай)",
|
||||
"Keep Versions": "Пази версии",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": " Първо най-големите",
|
||||
"Last File Received": "Последния получен файл",
|
||||
"Last Scan": "Последно сканирана",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Пауза",
|
||||
"Pause All": "Пауза на всички",
|
||||
"Paused": "На пауза",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Pending changes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Периодично сканиране, през определен интервал, без мониторинг за промени",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Периодично сканиране, през определен интервал, и мониторинг за промени",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Comentar, quant s'utilitza al principi d'una línia",
|
||||
"Compression": "Compresió",
|
||||
"Configured": "Configurat",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Error de connexió",
|
||||
"Connection Type": "Tipus de connexió",
|
||||
"Connections": "Connexions",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Desactivat l'escaneig periòdic i errada al rastreig continu de canvis, es reintentarà cada 1 minut:",
|
||||
"Discard": "Descartar",
|
||||
"Disconnected": "Desconnectat",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Descobert",
|
||||
"Discovery": "Descobriment",
|
||||
"Discovery Failures": "Fallades al Descobriment",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Presentador",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversió de la condició donada (per exemple no excloure)",
|
||||
"Keep Versions": "Mantindre versions",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "El més gran primer",
|
||||
"Last File Received": "Darrer fitxer rebut",
|
||||
"Last Scan": "Últim escaneig",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pausa",
|
||||
"Pause All": "Pausa Tot",
|
||||
"Paused": "Pausat",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Canvis pendents",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Escaneig periòdic a l'interval determinat i desactivat el rastreig continu de canvis",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Escaneig periòdic a l'interval determinat i activat el rastreig continu de canvis",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Pokud použito na jeho začátku, je řádek považován za komentář",
|
||||
"Compression": "Komprese",
|
||||
"Configured": "Nastaveno",
|
||||
"Connected (Unused)": "Připojeno (nepoužité)",
|
||||
"Connection Error": "Chyba připojení",
|
||||
"Connection Type": "Typ připojení",
|
||||
"Connections": "Spojení",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Periodické skenování vypnuto; nastavení sledování změn se nezdařilo, opětovný pokus každou 1 min:",
|
||||
"Discard": "Zahodit",
|
||||
"Disconnected": "Odpojeno",
|
||||
"Disconnected (Unused)": "Odpojeno (nepoužité)",
|
||||
"Discovered": "Objeveno",
|
||||
"Discovery": "Oznamování",
|
||||
"Discovery Failures": "Nezdary při oznamování",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Zavaděč",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Převrácení dané podmínky (např. nevynechat)",
|
||||
"Keep Versions": "Kolik verzí ponechávat",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Od největších",
|
||||
"Last File Received": "Poslední přijatý soubor",
|
||||
"Last Scan": "Poslední sken",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pozastavit",
|
||||
"Pause All": "Pozastavit vše",
|
||||
"Paused": "Pozastaveno",
|
||||
"Paused (Unused)": "Pozastaveno (nepoužité)",
|
||||
"Pending changes": "Čekající změny",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodické skenování podle zadaného intervalu; sledování změn vypnuto",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodické skenování podle zadaného intervalu; sledování změn zapnuto",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Kommentar, når den bruges i starten af en linje",
|
||||
"Compression": "Anvend komprimering",
|
||||
"Configured": "Konfigureret",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Tilslutnings fejl",
|
||||
"Connection Type": "Tilslutningstype",
|
||||
"Connections": "Forbindelser",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Deaktiverede periodisk skanning fra og lykkedes ikke med at opsætte overvågning af ændringer; prøver igen hvert minut:",
|
||||
"Discard": "Behold ikke",
|
||||
"Disconnected": "Ikke tilsluttet",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Opdaget",
|
||||
"Discovery": "Opslag",
|
||||
"Discovery Failures": "Fejl ved opdagelse",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Introducerende enhed",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Det omvendte (dvs. undlad ikke)",
|
||||
"Keep Versions": "Behold versioner",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Største først",
|
||||
"Last File Received": "Senest modtagne fil",
|
||||
"Last Scan": "Seneste skanning",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pause",
|
||||
"Pause All": "Sæt alt på pause",
|
||||
"Paused": "På pause",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Ventende ændringer",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodisk skanning med et givent interval og deaktiveret overvågning af ændringer",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodisk skanning med et givent interval og aktiveret overvågning af ændringer",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Kommentar, wenn am Anfang der Zeile benutzt.",
|
||||
"Compression": "Komprimierung",
|
||||
"Configured": "Konfiguriert",
|
||||
"Connected (Unused)": "Verbunden (Nicht genutzt)",
|
||||
"Connection Error": "Verbindungsfehler",
|
||||
"Connection Type": "Verbindungstyp",
|
||||
"Connections": "Verbindungen",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Deaktivierter periodischer Scann, fehlgeschlagene überprüfen auf Änderungen und erneuter versuch in 1 Min:",
|
||||
"Discard": "Verwerfen",
|
||||
"Disconnected": "Getrennt",
|
||||
"Disconnected (Unused)": "Getrennt (Nicht genutzt)",
|
||||
"Discovered": "Ermittelt",
|
||||
"Discovery": "Gerätesuche",
|
||||
"Discovery Failures": "Gerätesuchfehler",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Verteilergerät",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Umkehrung der angegebenen Bedingung (z.B. schließe nicht aus)",
|
||||
"Keep Versions": "Versionen erhalten",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Größte zuerst",
|
||||
"Last File Received": "Letzte Änderung",
|
||||
"Last Scan": "Letzter Scan",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pause",
|
||||
"Pause All": "Alles pausieren",
|
||||
"Paused": "Pausiert",
|
||||
"Paused (Unused)": "Pausiert (Nicht genutzt)",
|
||||
"Pending changes": "Ausstehende Änderungen",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodisches Scannen bei angegebenen Intervall und deaktivierter Überwachung von Änderungen",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodisches Scannen bei angegebenen Intervall und aktivierter Überwachung von Änderungen",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Σχόλιο, όταν χρησιμοποιείται στην αρχή μιας γραμμής",
|
||||
"Compression": "Συμπίεση",
|
||||
"Configured": "Βάσει ρύθμισης",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Σφάλμα σύνδεσης",
|
||||
"Connection Type": "Τύπος Σύνδεσης",
|
||||
"Connections": "Συνδέσεις",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Έχει απενεργοποιηθεί η τακτική σάρωση και απέτυχε η ενεργοποίηση επιτήρησης αλλαγών. Γίνεται νέα προσπάθεια κάθε 1m:",
|
||||
"Discard": "Discard",
|
||||
"Disconnected": "Αποσυνδεδεμένη",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Βάσει ανεύρεσης",
|
||||
"Discovery": "Ανεύρεση συσκευών",
|
||||
"Discovery Failures": "Αποτυχίες ανεύρεσης συσκευών",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Βασικός κόμβος",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Αντιστροφή της δοσμένης συνθήκης (π.χ. να μην εξαιρείς) ",
|
||||
"Keep Versions": "Διατήρηση εκδόσεων",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Το μεγαλύτερο πρώτα",
|
||||
"Last File Received": "Πιο πρόσφατο αρχείο",
|
||||
"Last Scan": "Τελευταία Σάρωση",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Παύση",
|
||||
"Pause All": "Παύση όλων",
|
||||
"Paused": "Σε παύση",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Pending changes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Τακτική σάρωση ανά καθορισμένο διάστημα και απενεργοποίηση επιτήρησης αλλαγών",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Τακτική σάρωση ανά καθορισμένο διάστημα και ενεργοποίηση επιτήρησης αλλαγών",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Comment, when used at the start of a line",
|
||||
"Compression": "Compression",
|
||||
"Configured": "Configured",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Connection Error",
|
||||
"Connection Type": "Connection Type",
|
||||
"Connections": "Connections",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:",
|
||||
"Discard": "Discard",
|
||||
"Disconnected": "Disconnected",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Discovered",
|
||||
"Discovery": "Discovery",
|
||||
"Discovery Failures": "Discovery Failures",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Introducer",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversion of the given condition (i.e. do not exclude)",
|
||||
"Keep Versions": "Keep Versions",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Largest First",
|
||||
"Last File Received": "Last File Received",
|
||||
"Last Scan": "Last Scan",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pause",
|
||||
"Pause All": "Pause All",
|
||||
"Paused": "Paused",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Pending changes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodic scanning at given interval and disabled watching for changes",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodic scanning at given interval and enabled watching for changes",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Comment, when used at the start of a line",
|
||||
"Compression": "Compression",
|
||||
"Configured": "Configured",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Connection Error",
|
||||
"Connection Type": "Connection Type",
|
||||
"Connections": "Connections",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:",
|
||||
"Discard": "Discard",
|
||||
"Disconnected": "Disconnected",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Discovered",
|
||||
"Discovery": "Discovery",
|
||||
"Discovery Failures": "Discovery Failures",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Introducer",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversion of the given condition (i.e. do not exclude)",
|
||||
"Keep Versions": "Keep Versions",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Largest First",
|
||||
"Last File Received": "Last File Received",
|
||||
"Last Scan": "Last Scan",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pause",
|
||||
"Pause All": "Pause All",
|
||||
"Paused": "Paused",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Pending changes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodic scanning at given interval and disabled watching for changes",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodic scanning at given interval and enabled watching for changes",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Komento, kiam uzita ĉe la komenco de lineo",
|
||||
"Compression": "Densigo",
|
||||
"Configured": "Agordita",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Eraro de Konekto",
|
||||
"Connection Type": "Tipo de Konekto",
|
||||
"Connections": "Konektoj",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Malebligita perioda skanado kaj malsukcesis agordi rigardadon je ŝanĝoj. Provante denove ĉiuminute:",
|
||||
"Discard": "Forĵeti",
|
||||
"Disconnected": "Malkonektita",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Malkovrita",
|
||||
"Discovery": "Malkovro",
|
||||
"Discovery Failures": "Malsukcesoj de Malkovro",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Enkondukanto",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversigo de la donita kondiĉo (t.e. ne ekskludi)",
|
||||
"Keep Versions": "Konservi Versiojn",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Plej Granda Unue",
|
||||
"Last File Received": "Lasta Dosiero Ricevita",
|
||||
"Last Scan": "Lasta Skano",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Paŭzu",
|
||||
"Pause All": "Paŭzu Ĉion",
|
||||
"Paused": "Paŭzita",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Pritraktataj ŝanĝoj",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Perioda skanado ĉe donita intervalo kaj malebligita rigardado je ŝanĝoj",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Perioda skanado ĉe donita intervalo kaj ebligita rigardado je ŝanĝoj",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Comentar, cuando se usa al comienzo de una línea",
|
||||
"Compression": "Compresión",
|
||||
"Configured": "Configurado",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Error de conexión",
|
||||
"Connection Type": "Tipo de conexión",
|
||||
"Connections": "Conexiones",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Desactivado el escaneo periódico y falló la activación de la vigilancia de cambios, reintentando cada 1 minuto:",
|
||||
"Discard": "Descartar",
|
||||
"Disconnected": "Desconectado",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Descubierto",
|
||||
"Discovery": "Descubrimiento",
|
||||
"Discovery Failures": "Fallos de Descubrimiento",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Presentador",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversión de la condición dada (por ejemplo, \"no excluir\")",
|
||||
"Keep Versions": "Mantener versiones",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Más grande primero",
|
||||
"Last File Received": "Última actualización",
|
||||
"Last Scan": "Último escaneo",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pausar",
|
||||
"Pause All": "Pausar todo",
|
||||
"Paused": "Pausado",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Cambios pendientes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Escaneo periódico en un intervalo determinado y desactivada la vigilancia de cambios",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Escaneo periódico en un intervalo determinado y activada la vigilancia de cambios",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Comentar, cuando se usa al comienzo de una línea",
|
||||
"Compression": "Compresión",
|
||||
"Configured": "Configurado",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Error de conexión",
|
||||
"Connection Type": "Tipo de conexión",
|
||||
"Connections": "Conexiones",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Se desactivó el escaneo periódico y falló la configuración para detectar cambios, volviendo a intentarlo cada 1 m:",
|
||||
"Discard": "Descartar",
|
||||
"Disconnected": "Desconectado",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Descubierto",
|
||||
"Discovery": "Descubrimiento",
|
||||
"Discovery Failures": "Fallos de Descubrimiento",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Presentador",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversión de la condición dada (por ejemplo, \"no excluir\")",
|
||||
"Keep Versions": "Mantener versiones",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Más grande primero",
|
||||
"Last File Received": "Última actualización",
|
||||
"Last Scan": "Último escaneo",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pausar",
|
||||
"Pause All": "Pausar todo",
|
||||
"Paused": "Pausado",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Cambios pendientes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Escaneando periódicamente a un intervalo dado y detección de cambios desactivada",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Escaneando periódicamente a un intervalo dado y detección de cambios activada",
|
||||
|
||||
409
gui/default/assets/lang/lang-eu.json
Normal file
409
gui/default/assets/lang/lang-eu.json
Normal file
@@ -0,0 +1,409 @@
|
||||
{
|
||||
"A device with that ID is already added.": "Id hori duen tresna bat jadanik bada",
|
||||
"A negative number of days doesn't make sense.": "0 edo zenbaki positiboa onartzen da bakarrik",
|
||||
"A new major version may not be compatible with previous versions.": "Aldaketa garrantzitsuak dituen bertsio berri bat ez da beharbada bateragarria izanen bertsio zaharragoekin.",
|
||||
"API Key": "API giltza",
|
||||
"About": "Honi buruz",
|
||||
"Action": "Egintza",
|
||||
"Actions": "Egintzak",
|
||||
"Add": "Gehitu",
|
||||
"Add Device": "Tresna gehitu",
|
||||
"Add Folder": "Karpeta gehitu",
|
||||
"Add Remote Device": "Urrundikako tresna bat gehitu",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Gure tresna zerrendan tresnak gehitzea baimendu, partekatzeetan.",
|
||||
"Add new folder?": "Karpeta berria gehitu?",
|
||||
"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.": "Gainera, berresplorazio osoaren tartea handitu egingo da (60 aldiz, hau da, lehenetsitako balio berria, 1 ordukoa). Halaber, eskuz konfigura dezakezu karpeta bakoitzerako, Ez hautatu ondoren.",
|
||||
"Address": "Helbidea",
|
||||
"Addresses": "Helbideak",
|
||||
"Advanced": "Aitzinatua",
|
||||
"Advanced Configuration": "Konfigurazio aitzinatua",
|
||||
"Advanced settings": "Parametro aitzinatuak",
|
||||
"All Data": "Datu guziak",
|
||||
"Allow Anonymous Usage Reporting?": "Izenik gabeko erabiltze erreportak baimendu?",
|
||||
"Allowed Networks": "Sare baimenduak",
|
||||
"Alphabetic": "Alfabetikoa",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Kanpoko kontrolagailu batek fitxategien bertsioak kudeatzen ditu. Fitxategiak kendu behar ditu errepertorio sinkronizatuan.",
|
||||
"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.": "Kanpoko kontrolagailu batek fitxategien bertsioak kudeatzen ditu. Fitxategiak kendu behar ditu errepertorio sinkronizatuan. Aplikaziorako ibilbideak espazioak baditu, komatxo artean egon behar du.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Kanpoko kontrolagailu batek fitxeroen bertsioak erabiltzen ditu. Fitxeroak errepertorio sinkronizatutik desagertaraztea berari doakio.",
|
||||
"Anonymous Usage Reporting": "Izenik gabeko erabiltze erreportak",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Erabilera anonimoko txostenaren formatua aldatu egin da. Formatu berria erabili nahi duzu?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Sarrarazle deitzen duzun tresna batean gehitua izanen den edozein tresna, zurean ere gehitua izanen da.",
|
||||
"Are you sure you want to remove device {%name%}?": "Ziur zaude {{name}} gailua ezabtu nahi duzula?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Ziur zaude {{label}} karpeta ezabatu nahi duzula?",
|
||||
"Are you sure you want to restore {%count%} files?": "Ziur zaude {{count}} fitxategi berreskuratu nahi dituzula? ",
|
||||
"Are you sure you want to upgrade?": "Ziur zaude eguneratu nahi duzula?",
|
||||
"Auto Accept": "Onartu automatikoki",
|
||||
"Automatic Crash Reporting": "Hutsegite txosten automatikoa",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Eguneratze automatiko sistemak iraunkor bertsioen eta aitzineko bertsioen artean hautatzea proposatzen du",
|
||||
"Automatic upgrades": "Eguneratze automatikoak",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Eguneratze automatikoak beti daude gaituta jaurtikitako bertsioetarako.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Gailu honek lehenetsitako ibilbidean iragartzen dituen karpetak automatikoki sortu edo partekatu.",
|
||||
"Available debug logging facilities:": "Arazketa-erregistroko funtzio erabilgarriak:",
|
||||
"Be careful!": "Kasu emazu!",
|
||||
"Bugs": "Akatsak",
|
||||
"CPU Utilization": "Prozesadorearen erabiltzea",
|
||||
"Changelog": "Bertsioen historia",
|
||||
"Clean out after": "Garbi …. epearen ondotik",
|
||||
"Click to see discovery failures": "Klik egin hutsegiteak ikusteko",
|
||||
"Close": "Hetsi",
|
||||
"Command": "Kontrolagailua",
|
||||
"Comment, when used at the start of a line": "Komentarioa, lerro baten hastean delarik",
|
||||
"Compression": "Trinkotze",
|
||||
"Configured": "Konfiguratua",
|
||||
"Connected (Unused)": "Konektatuta (erabili gabe)",
|
||||
"Connection Error": "Konexio hutsa",
|
||||
"Connection Type": "Konexio mota",
|
||||
"Connections": "Konexioak",
|
||||
"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.": "Orain Syncthing-en eskuragarri dago aldaketen bilaketa etengabea. Disko-aldaketak hautemango dira, eta aldatutako ibilbideetan bakarrik egingo da eskaneatzea. Onurak aldaketak azkarrago zabaltzea eta eskaneatze oso gutxiago behar izatea dira.",
|
||||
"Copied from elsewhere": "Beste nunbaitik kopiatua",
|
||||
"Copied from original": "Jatorrizkotik kopiatua",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Copyright 2014-2016, ekarle hauk:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright 2014-2017, ekarle hauk:",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Copyright 2014-2019 ekarle hauek:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Baztertze modelo batzuen sortzea, dagoen fitxategiari ordaina ezartzea: {{path}}",
|
||||
"Currently Shared With Devices": "Gaur egun tresnekin partekatua",
|
||||
"Danger!": "Lanjera !",
|
||||
"Debugging Facilities": "Arazketa zerbitzuak",
|
||||
"Default Folder Path": "Partekatzearen sustrai bide lehenetsia",
|
||||
"Deleted": "Kendua",
|
||||
"Deselect All": "Hautaketa guztia kendu",
|
||||
"Deselect devices to stop sharing this folder with.": "Desautatu karpeta honekin partekatu nahi ez dituzun gailuak.",
|
||||
"Device": "Tresna",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Tresna \"{{name}}\" ({{device}} {{address}} era) konektatu nahi du. Onhartzen duzu ?",
|
||||
"Device ID": "Tresnaren ID-a",
|
||||
"Device Identification": "Tresnaren identifikazioa",
|
||||
"Device Name": "Tresnaren izena",
|
||||
"Device rate limits": "Gailuaren abiadura mugak",
|
||||
"Device that last modified the item": "Itema azkenekoz aldatu zuen gailua",
|
||||
"Devices": "Tresnak",
|
||||
"Disable Crash Reporting": "Desaktibatu blokeatzeko txosten automatikoen bidalketa",
|
||||
"Disabled": "Desgaitua",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Aldizkako miaketa eta aldaketen kontrola desgaitu dira",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Aldizkako miaketa desgaitu da eta aldaketen kontrola gaitu da",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Eskaneatze periodikoa desaktibatu da eta aldaketak detektatzeko konfigurazioak huts egin du, berriz ere 1 m-tik behin saiatuz:",
|
||||
"Discard": "Baztertu",
|
||||
"Disconnected": "Deskonektatua",
|
||||
"Disconnected (Unused)": "Deskonektatuta (erabili gabe)",
|
||||
"Discovered": "Agertua",
|
||||
"Discovery": "Agertzea",
|
||||
"Discovery Failures": "Agertze hutsegiteak",
|
||||
"Do not restore": "Ez berrezarri",
|
||||
"Do not restore all": "Ez berrezarri denak",
|
||||
"Do you want to enable watching for changes for all your folders?": "Zure karpeta guztietan aldaketen kontrola aktibatu nahi duzu?",
|
||||
"Documentation": "Dokumentazioa",
|
||||
"Download Rate": "Deskargatzearen bit-tasa",
|
||||
"Downloaded": "Deskargatua",
|
||||
"Downloading": "Deskargatzea",
|
||||
"Edit": "Aldatu",
|
||||
"Edit Device": "Tresna aldatzea",
|
||||
"Edit Folder": "Partekatze aldatzea",
|
||||
"Editing": "Aldaketak",
|
||||
"Editing {%path%}.": "Muntatzea {{path}}",
|
||||
"Enable Crash Reporting": "Aktibatu blokeatzeko txosten automatikoen bidalketa",
|
||||
"Enable NAT traversal": "NAT translazioa aktibatu",
|
||||
"Enable Relaying": "Aldizkatzea posible",
|
||||
"Enabled": "Aktibatuta",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Negatiboa ez den zenbaki bat hauta ezazu (\"2.35\" adib.) bai eta unitate bat. Disko osoaren ehuneko espazioa",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Abantailatua ez den portu zenbalki bat sar ezazu (1024 - 65535)",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": " (\"tcp://ip:ataka\", \"tcp://izena:ataka\") zuzenbideak sar, krakotx batez separatuak edo bestenaz \"dynamic\", zuzenbidearen xekatze automatikoa aktibatzeko",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Sartu komaz bereizitako helbideak (\"tcp://ip:port\", \"tcp://host:port\"), edo \"dynamic\" helbidea automatikoki bilatzeko.",
|
||||
"Enter ignore patterns, one per line.": "Ezkluzio filtroak sar, lerro bakoitzean bat bakarrik.",
|
||||
"Enter up to three octal digits.": "Sartu 3 digitu bitarte",
|
||||
"Error": "Hutsa",
|
||||
"External File Versioning": "Fitxategi bertsioen kanpoko kudeaketa",
|
||||
"Failed Items": "Huts egin duten fitxategiak",
|
||||
"Failed to load ignore patterns": "Huts egin du baztertze ereduak kargatzean",
|
||||
"Failed to setup, retrying": "Konfigurazioan huts egitea, berriro saiatuz",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "IPv6 zerbitzariei buruzko konexioak huts eginen du, IPv6 konektibitaterik ez bada",
|
||||
"File Pull Order": "Fitxategiak berreskuratzeko ordena",
|
||||
"File Versioning": "Fitxategiak zaintzeko metodoa",
|
||||
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Aldaketa bilaketetan, fitxeroen baimen bitak ez dira kontuan hartuko. Fitxero FAT sistimetan erabilia.",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Fitxategiak .stbersioak errepertorioan lekutuak dira, Syncthing-ek ordezkatzen edo kentzen dituelarik",
|
||||
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": ".stbersioak azpi karpetan lekutuko dira fitxeroak, Syncthing-ek aldatu edo ezeztatuko dituelarik. Beren helbide errelatiboak hor berean berriz sortuak izanen dira, behar balin bada",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Syncthing-ek aldatzen edo kentzen dituelarik, fitxeroak \".stbertsioak\" peko-errepertoriorat lekutuak dira, jatorrizkoaren berdin berdina den zuhaitz-formako batean",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": ".stbersioak azpi karpetan lekutuko eta ordu-markatuko dira fitxeroak, egitura errelatibo berdin batean, Syncthing-ek aldatu edo ezeztatuko dituelarik.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Beste tresnetan eginak izanen diren aldaketetatik zainduak izanen dira fitxeroak; haatik, tresna huntan egindako aldaketak besteeri hedatuak izanen dira.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Fitxategiak klusterretik sinkronizatzen dira, baina tokian egindako aldaketak ez dira beste gailu batzuetara bidaliko.",
|
||||
"Filesystem Notifications": "Fitxategi-sistemaren jakinarazpenak",
|
||||
"Filesystem Watcher Errors": "Fitxategi-sistemaren zaindariaren erroreak",
|
||||
"Filter by date": "Dataz iragazi",
|
||||
"Filter by name": "Izenaz iragazi",
|
||||
"Folder": "Partekatze",
|
||||
"Folder ID": "ID partekatze",
|
||||
"Folder Label": "Partekatzearen izena",
|
||||
"Folder Path": "Partekatzearen sustrai bidea",
|
||||
"Folder Type": "Partekatze mota",
|
||||
"Folders": "Partekatzeak",
|
||||
"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.": "Hurrengo karpetetan errorea gertatu da aldaketak bilatzen hastean. Berriro saiatuko da minuturo, beraz, akatsak laster konpon daitezke. Jarraitzen badute, saiatu azpiko arazoa konpontzen eta eskatu laguntza, ezin baduzu.",
|
||||
"Full Rescan Interval (s)": "Berriz eskaneatzeko tartea osatu da (s)",
|
||||
"GUI": "Interfaze grafikoa",
|
||||
"GUI Authentication Password": "Interfaze grafiko pasahitza",
|
||||
"GUI Authentication User": "Interfaze grafiko erabiltzaile baimendua",
|
||||
"GUI Listen Address": "Interfaze grafiko helbidea",
|
||||
"GUI Listen Addresses": "Interfaze grafiko helbideak",
|
||||
"GUI Theme": "Interfaze grafiko tema",
|
||||
"General": "Orokorra",
|
||||
"Generate": "Sortu",
|
||||
"Global Changes": "Azken aldaketak",
|
||||
"Global Discovery": "Aurkikuntza orokorra",
|
||||
"Global Discovery Servers": "Orokor aurkikuntza zerbitzaria",
|
||||
"Global State": "Egoera orokorra",
|
||||
"Help": "Laguntza",
|
||||
"Home page": "Harrera",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Hala ere, zure ezarpenen arabera baliteke aktibatu nahi ez izatea. Txostenen bidalketa automatikoa desaktibatu dugu zuretzat.",
|
||||
"Ignore": "Kontuan ez hartu",
|
||||
"Ignore Patterns": "Baztertzeak",
|
||||
"Ignore Permissions": "Baimenak kontuan ez hartu",
|
||||
"Ignored Devices": "Bazter utzitako tresnak",
|
||||
"Ignored Folders": "Bazter utzitako karpetak",
|
||||
"Ignored at": "Hemen baztertuak",
|
||||
"Incoming Rate Limit (KiB/s)": "Deskargatze emari muga (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Behar ez den konfigurazio batek zuen partekatzetan makurrak egin ditzake eta Syncthing ezin erabilia utzi",
|
||||
"Introduced By": "...k sartua",
|
||||
"Introducer": "Tresna sarrarazlea",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Emana izan den baldintza alderantziz eman (i.e ez baztertu)",
|
||||
"Keep Versions": "Gorde bertsioak",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Handienak lehenik",
|
||||
"Last File Received": " Azkenik eskuratu fitxategia",
|
||||
"Last Scan": "Azken azterketa",
|
||||
"Last seen": "Azken agerraldia",
|
||||
"Later": "Berantago",
|
||||
"Latest Change": "Azken aldaketa",
|
||||
"Learn more": "Gehiago jakiteko",
|
||||
"Limit": "Muga",
|
||||
"Listeners": "Entzungailuak",
|
||||
"Loading data...": "Datuak kargatzen...",
|
||||
"Loading...": "Kargatzen...",
|
||||
"Local Additions": "Tokiko gehikuntzak",
|
||||
"Local Discovery": "Lekuko aurkikuntza",
|
||||
"Local State": "Lekuko egoera",
|
||||
"Local State (Total)": "Lekuko egoera (Osoa)",
|
||||
"Locally Changed Items": "Tokian aldatutako elementuak",
|
||||
"Log": "Erregistroa",
|
||||
"Log tailing paused. Click here to continue.": "Erregistroaren jarraipena gelditua. Egin klik hemen jarraitzeko.",
|
||||
"Log tailing paused. Scroll to bottom continue.": "Erregistroaren jarraipena gelditua. Mugitu kurtsorea behealderaino, jarraitzeko.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Erregistroaren desplazamendua etenaldian dago. Mugitu beherantz jarraitzeko.",
|
||||
"Logs": "Erregistroak",
|
||||
"Major Upgrade": "Eguneratze nagusia",
|
||||
"Mass actions": "Egintza anitzak",
|
||||
"Master": "Nagusia",
|
||||
"Maximum Age": "Adin gehiena",
|
||||
"Metadata Only": "Metadatuak bakarrik",
|
||||
"Minimum Free Disk Space": "Diskoan gutieneko leku libroa ",
|
||||
"Mod. Device": "Gailu aldatzailea",
|
||||
"Mod. Time": "Ordua aldatu",
|
||||
"Move to top of queue": "Lerro bururat lekuz alda",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Hein anitzerako jokerra (errepertorio eta azpi errepertorioeri dagokiona)",
|
||||
"Never": "Sekulan",
|
||||
"New Device": "Tresna berria",
|
||||
"New Folder": "Partekatze berria",
|
||||
"Newest First": "Berrienak lehenik",
|
||||
"No": "Ez",
|
||||
"No File Versioning": "Fitxategi bersioen kontrolik ez",
|
||||
"No files will be deleted as a result of this operation.": "Eragiketa horren ondorioz, ez da artxiborik ezabatuko.",
|
||||
"No upgrades": "Eguneratzerik ez",
|
||||
"Normal": "Normala",
|
||||
"Notice": "Jakinaraztea",
|
||||
"OK": "Ados",
|
||||
"Off": "Desgaitu",
|
||||
"Oldest First": "Zaharrenak lehenik",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Partekatzearen izen hautuzkoa eta atsegina, zure gisa. Tresna bakotxean desberdina izaiten ahal da.",
|
||||
"Options": "Hautuzkoak",
|
||||
"Out of Sync": "Ez sinkronizatua",
|
||||
"Out of Sync Items": "Ez sinkronizatu elementuak",
|
||||
"Outgoing Rate Limit (KiB/s)": "Bidaltze emari gehienekoa (KiB/s)",
|
||||
"Override Changes": "Aldaketak desegin",
|
||||
"Path": "Bidexka",
|
||||
"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": "Lekuko tresnaren partekatzeari buruzko bidea. Ez balitz, asmatu beharko da bat. Programarenari, baitezpadako bide bat sartzen ahal duzu (adibidez \"/home/ni/Sync/Etsenplua\") edo bestenaz bide errelatibo bat (adibidez \"..\\Partekatzeak\\Etsenplua\" - instalazio mugikor batentzat baliagarria). Tildea (~, edo ~+Espazioa Windows XP+Azerty-n) erabil litzateke laburbide gisa",
|
||||
"Path where new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {%tilde%}.": "Automatikoki onartutako karpeta berrien ibilbidea sortuko da, baita IUren bidez karpeta berriak gehitzean iradokitako ibilbide lehenetsia ere. (~) letra {{tilde}} -ra hedatzen da.",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Kopiak kontserbatzeko bidea (hutsa utz ezazu, .steversioen ohizko bidearentzat, dosier partekatuan)",
|
||||
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Kopiak kontserbatzeko bidea (hutsa utz ezazu, .stversioen ohizko dosierarentzat, karpeta partekatuan)",
|
||||
"Pause": "Pausa",
|
||||
"Pause All": "Geldi dena",
|
||||
"Paused": "Gelditua",
|
||||
"Paused (Unused)": "Geldi (erabili gabe)",
|
||||
"Pending changes": "Egiteke dauden aldaketak",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Emandako tartearen aldizkako miaketa, eta desaktibatuta aldaketak ikusteko",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Emandako tartearen aldizkako miaketa, eta aktibatuta aldaketak ikusteko",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Emandako tartearen aldizkako miaketa, eta huts egin du aldaketak ikusteko ezarpenak, berriro saiatuz minuturo:",
|
||||
"Permissions": "Baaimenak",
|
||||
"Please consult the release notes before performing a major upgrade.": "Aktualizatze garrantzitsu bat egin baino lehen, bertsioaren oharrak begira itzazu.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Konfigurazio leihoan asma itzazu erabiltzale izen bat eta pasahitz bat",
|
||||
"Please wait": "Pazientzia pixka bat, otoi",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Aurrezenbaki honen bidez fitxategiak ezaba daitezke direktorioak ezabatzeko.",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Aurrizkia honek patroiak letra larririk eta minuskularik gabe bat etorri behar duela adierazten du",
|
||||
"Preparing to Sync": "Sinkronizatzeko prestatzen",
|
||||
"Preview": "Aurrebista",
|
||||
"Preview Usage Report": "Erabiltze estatistika txostenaren aurrebista",
|
||||
"Quick guide to supported patterns": "Eredu konpatibleen gidaliburuxka",
|
||||
"RAM Utilization": "RAM aren erabiltzea",
|
||||
"Random": "Aleatorioa",
|
||||
"Receive Only": "Jaso bakarrik",
|
||||
"Recent Changes": "Aldaketa berriak",
|
||||
"Reduced by ignore patterns": "Baztertze eredu batzuk mugatuak",
|
||||
"Release Notes": "Bertsioen notak",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Azken zuzenketak eta funtzionalitateak edukitzen dituzte aitzin-bertsioek. Bi hilabete guziz egiten diren eguneratzeen berdinak dira.",
|
||||
"Remote Devices": "Beste tresnak",
|
||||
"Remove": "Kendu",
|
||||
"Remove Device": "Tresna kendu",
|
||||
"Remove Folder": "Karpeta kendu",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Partekatzearen erabilzaile izena. Dauden tresna guzietan berdin berdina izan behar du",
|
||||
"Rescan": "Berriz eskaneatu",
|
||||
"Rescan All": "Dena berriz eskaneatu",
|
||||
"Rescan Interval": "Berriz eskaneatzeko tartea",
|
||||
"Rescans": "Berriz eskaneatuak",
|
||||
"Restart": "Berriz piztu",
|
||||
"Restart Needed": "Berriz piztea beharrezkoa",
|
||||
"Restarting": "Berriz piztea martxan",
|
||||
"Restore": "Berrezarri",
|
||||
"Restore Versions": "Berrezarri bertsioak",
|
||||
"Resume": "Berriz hastea",
|
||||
"Resume All": "Dena berriz hastea",
|
||||
"Reused": "Berriz erabilia",
|
||||
"Revert Local Changes": "Bertan behera utzi aldaketa lokalak",
|
||||
"Running": "Lanean",
|
||||
"Save": "Grabatu",
|
||||
"Scan Time Remaining": "Gelditzen den azterketa denbora",
|
||||
"Scanning": "Azterketa martxan",
|
||||
"See external versioner help for supported templated command line parameters.": "Ikusi kanpoko bertsioen kudeatzailearen laguntza txantiloi bat erabiltzen duten komandoen lerro-parametroetarako.",
|
||||
"See external versioning help for supported templated command line parameters.": "Ikusi kanpoko bertsioen kudeatzailearen laguntza txantiloi bat erabiltzen duten komandoen lerro-parametroetarako.",
|
||||
"Select All": "Hautatu guztia",
|
||||
"Select a version": "Bertsio bat aukeratu",
|
||||
"Select additional devices to share this folder with.": " Tresna gehigarriak hauta itzazu partekatze honekin sinkronizatzeko ",
|
||||
"Select latest version": "Aukeratu azken bertsioa",
|
||||
"Select oldest version": "Aukeratu bertsio zaharrena",
|
||||
"Select the devices to share this folder with.": " Tresnak hauta itzazu partekatze honekin sinkronizatzeko ",
|
||||
"Select the folders to share with this device.": "Tresna honek erabiltzen dituen partekatzeak hauta itzazu",
|
||||
"Send & Receive": "Igorri eta errezibitu",
|
||||
"Send Only": "Igorrri bakarrik",
|
||||
"Settings": "Konfigurazioa",
|
||||
"Share": "Partekatu",
|
||||
"Share Folder": "Partekatzea",
|
||||
"Share Folders With Device": "Tresnarekin partekatzeak",
|
||||
"Share With Devices": "Tresnekin partekatu",
|
||||
"Share this folder?": "Partekatze hau onartzen duzu?",
|
||||
"Shared With": "...ekin partekatua",
|
||||
"Sharing": "Partekatuz",
|
||||
"Show ID": "Erakutsi ene ID-a",
|
||||
"Show QR": "Erakutsi QR-a",
|
||||
"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 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",
|
||||
"Shutdown": "Geldi",
|
||||
"Shutdown Complete": "Gelditua!",
|
||||
"Simple File Versioning": "Bertsioen segitze sinplifikatua",
|
||||
"Single level wildcard (matches within a directory only)": "Hein bakar bateko jokerra (karpetaren barnean bakarrik dagokiona)",
|
||||
"Size": "Tamaina",
|
||||
"Smallest First": "Ttipienak lehenik",
|
||||
"Some items could not be restored:": "Zenbat fitxategi ezin izan dira berreskuratu",
|
||||
"Source Code": "Iturri kodea",
|
||||
"Stable releases and release candidates": "iraunkor eta aintzin-bertsioak",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Iraunkor bertsioak bi astez (nonbait han) gibelatuak dira. Bitartean, aintzin-bertsio gisa probatuak izanen dira.",
|
||||
"Stable releases only": "Iraunkor bertsioak bakarrik",
|
||||
"Staggered File Versioning": "Bertsio mailakatuak",
|
||||
"Start Browser": "Web nabigatzailea piztu",
|
||||
"Statistics": "Estatistikak",
|
||||
"Stopped": "Gelditua!",
|
||||
"Support": "Foroa",
|
||||
"Support Bundle": "Laguntza-sorta",
|
||||
"Sync Protocol Listen Addresses": "Sinkronizatu protokoloaren entzun zuzenbideak",
|
||||
"Syncing": "Sinkronizazioa martxan",
|
||||
"Syncthing has been shut down.": "Syncthing gelditua izan da",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing-ek programa hauk integratzen ditu (edo programa hauetatik datozten elementuak):",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing software librea da eta kode irekikoa, MPL v2.0 lizentziarekin.",
|
||||
"Syncthing is restarting.": "Syncthing berriz pizten ari",
|
||||
"Syncthing is upgrading.": "Syncthing aktualizatzen ari da",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing-en bidez, automatikoki bidal diezazkiekezu garatzaileei blokeo-txostenak. Funtzio hau berez aktibatuta dago.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Iduri luke Syncthing gelditua dela, edo bestenaz arrazo bat bada interneten konekzioarekin. Berriz entsea zaitez…",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Iduri luke Syncthing-ek arazo bat duela zure eskaera tratatzeko. Otoi, orrialdea freska ezazu edo bestenaz, arazoak segitzen badu, Syncthing berriz pitz ezazu .",
|
||||
"Take me back": "Eraman nazazu atzera",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Erabiltzailearen Interfaze Grafikoaren GUI helbidea gainidatzita dago hasierako aukerengatik. Hemengo aldaketek ez dute ondoriorik izango gainidatzi aktibo dagoen bitartean.",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing-en administrazio interfazea pentsatua da urrundikako helbideak pasahitzik gabe onartzeko !",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Estadistikak zuzen bide honetan publikoki ikusgarriak dira",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigurazioa grabatua izan da bainan ez aktibatua. Syncthing berriz piztu behar da konfigurazio berria berriz aktibatzeko.",
|
||||
"The device ID cannot be blank.": "Tresnaren ID-a ez da hutsa izaiten ahal.",
|
||||
"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).": "Sartu behar den tresnaren ID-a atxemaiten ahal da menuan \"Ekintzak > ID-a erakuts\" (tresna urrunduarena). Espazio eta gioiak ez dira beharrezkoak.",
|
||||
"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.": "Erabileraren zifratu txostena egun guziz igorria da. Erabili diren plataformak, partekatzeen neurriak eta aplikazioaren bertsioen zerendatzeko balio du. Datu orokorrak aldatzen balin badira, mezu honen bidez ontzat emaitea eskatua izanen zaizu.\nErabiltzearen zifratu txostena egun guziz igorria da. Balio du erabiliak izan diren plataformak, partekatzeen izaria eta aplikazioaren bertsioak zerrendatzeko. Datu orokorrek aldatuak izan behar balute, mezu honen bidez ontzat emaitea eskatua izanen zaizu. Zure erabakia aldatzen ahal duzu Ekintzak/Konfigurazioa-ren bidez, baita igortzeen maiztasuna Ekintzak/ aitzinatua/Opzioak -en bidez.",
|
||||
"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.": "Sartu den tresnaren ID-ak iduri du ez duela balio. 52 edo 56-ko ezaugarriko kadena baten itxura behar luke, hizkiak, zifrak eta baita ere tarte edo gioiez egina.",
|
||||
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "Agingailu lerroaren lehen parametroa partekatzearen bidea da, eta bigarrena partekatzean den bide errelatiboa.",
|
||||
"The folder ID cannot be blank.": "Partekatzearen ID-a ez da hutsa izaiten ahal",
|
||||
"The folder ID must be unique.": "Partekatzearen ID-a bakarra izan behar da",
|
||||
"The folder path cannot be blank.": "Partekatzeari buruzko bidea ez da hutsa izaiten ahal",
|
||||
"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.": "Hunako tarteak erabiliak dira: lehen orduan bertsio bat kontserbatua da 30 segundu guziz. Lehen egunean, bertsio bat ordu bakoitz, lehen 30 egunetan bertsio bat egunero. Handik harat, adinaren mugetan egonez, bertsio bat astero.",
|
||||
"The following items could not be synchronized.": "Ondoko fitxero hauk ez dira sinkronizatuak ahal izan",
|
||||
"The following items were changed locally.": "Elementu hauek tokiz aldatu dira.",
|
||||
"The maximum age must be a number and cannot be blank.": "Gehieneko adinak zenbaki bat behar du izan eta ez da hutsa izaiten ahal.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Bertsio baten kontserbatzeko epe haundiena (egunez behar du izan. Jar ezazu zerotan bertsioak betirako atxikitzeko)",
|
||||
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "Diskoaren ehuneko espazioa hutsak zenbaki positibo bat behar du izan, 0 eta 100-en artekoa (100 barne)",
|
||||
"The number of days must be a number and cannot be blank.": "Egunen kopuruak numerikoa izan behar du eta ez da hutsa izaiten ahal",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Zikin ontzian elgar hizketak kontserbatzeko egun kopurua. Zerok \"betirako\" erran nahi du.",
|
||||
"The number of old versions to keep, per file.": "Atxikitzeko diren lehenagoko bertsioen kopurua, fitxero bakoitzarentzat",
|
||||
"The number of versions must be a number and cannot be blank.": "Bertsioen kopuruak numerikoa behar du izan eta ez da hutsa izaiten ahal",
|
||||
"The path cannot be blank.": "Bidea ez da hutsa izaiten ahal",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Ixuriaren emaria ez da negatiboa izaiten ahal (0 = mugarik gabekoa)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Ikerketaren tartea ez da segundo kopuru negatiboa izaiten ahal",
|
||||
"There are no devices to share this folder with.": "Ez dago partekatutako erabilera horri gehitzeko gailurik.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "Errorea zuzendua izanen delarik, automatikoki berriz entseatuak et sinkronizatuak izanen dira",
|
||||
"This Device": "Tresna hau",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Hunek errexki irakurtzen eta aldatzen uzten ahal du zure ordenagailuko edozein fitxero, nahiz eta sartu denak ez haizu izan!",
|
||||
"This is a major version upgrade.": "Aktualizatze garrantzitsu bat da",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Behar den espazio kontrolatzen du egokitze honek, zure erabiltzale partekatzea geritzatzen duen diskoan (hori da, indexazio datu-basean)",
|
||||
"Time": "Ordua",
|
||||
"Time the item was last modified": "Itema azkenekoz aldatu zen ordua",
|
||||
"Trash Can File Versioning": "Zakarrontzia",
|
||||
"Type": "Mota",
|
||||
"UNIX Permissions": "UNIX baimenak",
|
||||
"Unavailable": "Ez dago erabilgarri",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Ez dago erabilgarri/administratzaileak edo mantentzaileak desgaitu du",
|
||||
"Undecided (will prompt)": "Erabaki gabe (galdetuko da)",
|
||||
"Unignore": "Ez ikusia egin",
|
||||
"Unknown": "Ezezaguna",
|
||||
"Unshared": "Partekatua ez dena",
|
||||
"Unshared Devices": "Partekatzen ez diren gailuak",
|
||||
"Unused": "Ez baliatua",
|
||||
"Up to Date": "Eguneratua",
|
||||
"Updated": "Berritua",
|
||||
"Upgrade": "Aktualizatu",
|
||||
"Upgrade To {%version%}": "Egunetaratu {{version}}-ari buruz",
|
||||
"Upgrading": "Syncthing-en egunetaratzea",
|
||||
"Upload Rate": "Igortze emaria",
|
||||
"Uptime": "Erabiltze denbora",
|
||||
"Usage reporting is always enabled for candidate releases.": "Erabiltze estatiskitak aintzin-bertsioetan beti igorriak dira",
|
||||
"Use HTTPS for GUI": "HTTPS-a erabil ezazu GUI-arentzat",
|
||||
"Use notifications from the filesystem to detect changed items.": "Erabili fitxategi sistemaren jakinarazpenak aldatutako elementuak atzemateko",
|
||||
"Variable Size Blocks": "Tamaina aldakorreko blokeak",
|
||||
"Variable size blocks (also \"large blocks\") are more efficient for large files.": "Tamaina aldakorreko blokeak (\"bloke handiak\" barne) eraginkorragoak dira artxibo handietarako.",
|
||||
"Version": "Bertsioa",
|
||||
"Versions": "Bertsioak",
|
||||
"Versions Path": "Bertsioen kokalekua",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Bertsioak automatikoki ezeztatuak izanen dira, kontserbatzeko iraupen denbora pasatua badute edo bitartean onartua den kopurua (fitxategi bakoitzean) gainditua balin bada",
|
||||
"Waiting to Scan": "Eskaneatzeko zain",
|
||||
"Waiting to Sync": "Sinkronizatzeko zain",
|
||||
"Waiting to scan": "Eskaneatzeko zain",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Kasu, bide hau dagoen partekatze baten karpeta ahaidea da (adibidez, \"{{otherFolder}}\"). Segitzen baduzu, azpi-karpeta berri bat sortu behar duzu, bestenaz arazoak sortzen ahal dira, fitxategi kentzeak edo doblatzeak.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Kasu, bide hau dagoen partekatze baten karpeta ahaidea da (adibidez, \"{{otherFolderLabel}}\" ({{otherFolder}}). ",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Kasu, bide hau \"{{otherFolder}}\" partekatzearen azpi-karpeta da. Arazoak emaiten ahal ditu, fitxategi kentzeak edo doblatzeak, adibidez.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Kasu, bide hau \"{{otherFolderLabel}}\" ({{otherFolder}}) partekatzearen azpi-karpeta da. Arazoak emaiten ahal ditu, fitxategi kentzeak edo doblatzeak, adibidez.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Oharra: {{syncthingInotify}} moduko kanpoko behatzaile bat erabiltzen ari bazara, desaktibatuta dagoela ziurtatu behar duzu.",
|
||||
"Watch for Changes": "Aldaketak zaindu",
|
||||
"Watching for Changes": "Aldaketak zaintzen",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Aldaketen gainbegiratzeak aldaketa gehienen berri izaten du, aldian behin berriro aztertu gabe.",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "Tresna bat gehitzen duzularik, gogoan atxik ezazu zurea bestaldean gehitu behar dela ere",
|
||||
"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.": "Partekatze bat gehitzen delarik, gogoan atxik ezazu bere IDa erabilia dela errepertorioak lotzeko tresnen bitartez. ID-a hautskorra da eta partekatze hontan parte hartzen duten tresna guzietan berdina izan behar du.",
|
||||
"Yes": "Bai",
|
||||
"You can also select one of these nearby devices:": "Gertuko gailu hauetako bat ere hauta dezakezu:",
|
||||
"You can change your choice at any time in the Settings dialog.": "Zure hautua aldatzen ahal duzu \"Konfigurazio\" leihatilan",
|
||||
"You can read more about the two release channels at the link below.": "Bi banaketa kanal hauen bidez gehiago jakin dezakezu, lokarri honen bidez ",
|
||||
"You have no ignored devices.": "Ez duzu bazter utzitako tresnarik",
|
||||
"You have no ignored folders.": "Ez duzu bazter utzitako karpetarik",
|
||||
"You have unsaved changes. Do you really want to discard them?": "Gorde gabeko aldaketak dituzu. Ziur baztertu nahi dituzula?",
|
||||
"You must keep at least one version.": "Bertsio bat bederen behar duzu atxiki",
|
||||
"days": "Egunak",
|
||||
"directories": "Karpetak",
|
||||
"files": "Fitxategiak",
|
||||
"full documentation": "Dokumentazio osoa",
|
||||
"items": "Elementuak",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}}k \"{{folder}}\" partekatze hontan gomitatzen zaitu.",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}}k \"{{folderlabel}}\" ({{folder}}) hontan gomitatzen zaitu."
|
||||
}
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Kommentti, käytettäessä rivin alussa",
|
||||
"Compression": "Pakkaus",
|
||||
"Configured": "Konfiguroitu",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Yhteysvirhe",
|
||||
"Connection Type": "Yhteyden tyyppi",
|
||||
"Connections": "Yhteydet",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Ajoitettu skannaus pois päältä. Muutosten seurannan käyttöönotto epäonnistui, yritetään uudelleen minuutin välein:",
|
||||
"Discard": "Hylkää",
|
||||
"Disconnected": "Yhteys katkaistu",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Löydetty",
|
||||
"Discovery": "Etsintä",
|
||||
"Discovery Failures": "Etsinnässä tapahtuneet virheet",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Esittelijä",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Käänteinen ehto (t.s. älä ohita)",
|
||||
"Keep Versions": "Säilytä versiot",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Suurin ensin",
|
||||
"Last File Received": "Viimeksi vastaanotettu tiedosto",
|
||||
"Last Scan": "Viimeisin skannaus",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Keskeytä",
|
||||
"Pause All": "Keskeytä kaikki",
|
||||
"Paused": "Keskeytetty",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Odottavia muutoksia",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Ajoitettu skannaus päällä. Muutosten seuranta pois päältä",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Ajoitettu skannaus ja muutosten seuranta päällä",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Commentaire lorsque utilisé en début de ligne",
|
||||
"Compression": "Compression",
|
||||
"Configured": "Configurée",
|
||||
"Connected (Unused)": "Connecté (Non utilisé)",
|
||||
"Connection Error": "Erreur de connexion",
|
||||
"Connection Type": "Type de connexion",
|
||||
"Connections": "Connexions",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Analyse périodique désactivée et échec d'activation de la surveillance des changements. Nouvel essai toutes les 1mn :",
|
||||
"Discard": "Rejeter",
|
||||
"Disconnected": "Déconnecté",
|
||||
"Disconnected (Unused)": "Déconnecté (Non utilisé)",
|
||||
"Discovered": "Découvert",
|
||||
"Discovery": "Découverte",
|
||||
"Discovery Failures": "Échecs de découverte",
|
||||
@@ -89,7 +91,7 @@
|
||||
"Do not restore all": "Ne pas tout restaurer",
|
||||
"Do you want to enable watching for changes for all your folders?": "Voulez-vous activer la surveillance des changements sur tous vos partages ?",
|
||||
"Documentation": "Documentation",
|
||||
"Download Rate": "Débit de réception",
|
||||
"Download Rate": "Réception : Débit (Volume)",
|
||||
"Downloaded": "Reçu",
|
||||
"Downloading": "Réception",
|
||||
"Edit": "Gérer...",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Appareil introducteur",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inverser la condition donnée (i.e. ne pas exclure)",
|
||||
"Keep Versions": "Combien de versions conserver",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Les plus volumineux en premier",
|
||||
"Last File Received": "Dernier changement",
|
||||
"Last Scan": "Dernière analyse",
|
||||
@@ -191,7 +194,7 @@
|
||||
"Mod. Device": "Appareil modificateur",
|
||||
"Mod. Time": "Date de modification",
|
||||
"Move to top of queue": "Déplacer en haut de la file",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Joker multi niveaux (correspond aux répertoires et sous-répertoires)",
|
||||
"Multi level wildcard (matches multiple directory levels)": "N'importe quel nombre, dont 0, de n'importe quels caractères (dont le séparateur de répertoires).",
|
||||
"Never": "Jamais",
|
||||
"New Device": "Nouvel appareil",
|
||||
"New Folder": "Nouveau partage",
|
||||
@@ -205,7 +208,7 @@
|
||||
"OK": "OK",
|
||||
"Off": "Désactivée",
|
||||
"Oldest First": "Les plus anciens en premier",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Nom local, convivial et optionnel du partage, à votre guise. il peut être différent sur chaque appareil. Par notification initiale, il sera proposé tel quel aux nouveaux participants.\nAstuce : comme il est modifiable ultérieurement, pensez à indiquer un nom parlant pour les invités, puis renommez-le quand ils l'auront accepté (exemple d'un partage à deux membres où l'initiateur commence par donner son propre nom au partage, puis le renomme plus tard au nom du partenaire quand celui-ci l'a enregistré). Évitez les erreurs d'orthographe car ce nom servira aussi de base au chemin proposé en création (local et distant) et ce chemin est difficilement modifiable.",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Nom local, convivial et optionnel du partage, à votre guise. Il peut être différent sur chaque appareil. Par notification initiale, il sera proposé tel quel aux nouveaux participants.\nAstuce : comme il est modifiable ultérieurement, pensez à indiquer un nom parlant pour les invités, puis renommez-le quand ils l'auront accepté (exemple d'un partage à deux membres où l'initiateur commence par donner son propre nom au partage, puis le renomme plus tard au nom du partenaire quand celui-ci l'a accepté - Pensez au nom ~définitif~ du répertoire, modifiable plus bas à la création). Évitez les erreurs d'orthographe car ce nom servira aussi de base au chemin proposé en création (local et distant) et ce chemin est difficilement modifiable.",
|
||||
"Options": "Options",
|
||||
"Out of Sync": "Désynchronisé",
|
||||
"Out of Sync Items": "Éléments non synchronisés",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pause",
|
||||
"Pause All": "Tout suspendre",
|
||||
"Paused": "En pause",
|
||||
"Paused (Unused)": "En pause (Non utilisé)",
|
||||
"Pending changes": "Modifications en attente",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Analyse périodique à intervalle défini et surveillance des changements désactivée.",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Analyse périodique à intervalle défini et surveillance des changements activée.",
|
||||
@@ -289,7 +293,7 @@
|
||||
"Shutdown": "Arrêter",
|
||||
"Shutdown Complete": "Arrêté !",
|
||||
"Simple File Versioning": "Suivi simplifié des versions",
|
||||
"Single level wildcard (matches within a directory only)": "Joker à un seul niveau (correspond uniquement à l’intérieur du répertoire)",
|
||||
"Single level wildcard (matches within a directory only)": "N'importe quel nombre, dont 0, de n'importe quels caractères (sauf le séparateur de répertoires).",
|
||||
"Size": "Taille",
|
||||
"Smallest First": "Les plus petits en premier",
|
||||
"Some items could not be restored:": "Certains éléments n'ont pas pu être restaurés :",
|
||||
@@ -363,7 +367,7 @@
|
||||
"Upgrade": "Mettre à jour",
|
||||
"Upgrade To {%version%}": "Mettre à jour vers {{version}}",
|
||||
"Upgrading": "Mise à jour de Syncthing",
|
||||
"Upload Rate": "Débit d'envoi",
|
||||
"Upload Rate": "Envoi : Débit (Volume)",
|
||||
"Uptime": "Durée de fonctionnement",
|
||||
"Usage reporting is always enabled for candidate releases.": "L'envoi des statistiques d'utilisation est obligatoirement actif pour les versions préliminaires.",
|
||||
"Use HTTPS for GUI": "Utiliser l'HTTPS pour le GUI",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"Are you sure you want to remove device {%name%}?": "Bist der wis fan datsto apparaat {{name}} fuortsmite wolst?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Bist der wis fan datsto map {{label}} fuortsmite wolst?",
|
||||
"Are you sure you want to restore {%count%} files?": "Bist der wis fan datsto {{count}} triemen weromsette wolst?",
|
||||
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
|
||||
"Are you sure you want to upgrade?": "Bist der wis fan datsto upwardearre wolst?",
|
||||
"Auto Accept": "Auto-akseptaasje",
|
||||
"Automatic Crash Reporting": "Automatyske Rapportaazje fan Fêstrinners",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatyske fernijing biedt no de kar tusken stabyle ferzjes en ferzje kandidaten",
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Kommentaar, wannear as brûkt by it begjin fan in rige",
|
||||
"Compression": "Kompresje",
|
||||
"Configured": "Konfigureart",
|
||||
"Connected (Unused)": "Ferbûn (Net Brûkt)",
|
||||
"Connection Error": "Ferbiningsflater",
|
||||
"Connection Type": "Ferbiningstype",
|
||||
"Connections": "Ferbinings",
|
||||
@@ -60,13 +61,13 @@
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 de folgende Bydragers:",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 de folgende Bydragers:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Meitsje negear-patroanen dy in besteande triem oerskriuwe yn {{path}}.",
|
||||
"Currently Shared With Devices": "Currently Shared With Devices",
|
||||
"Currently Shared With Devices": "Op dit stuit Dielt mei Apparaten",
|
||||
"Danger!": "Gefaar!",
|
||||
"Debugging Facilities": "Debug-foarsjennings",
|
||||
"Default Folder Path": "Standert Map-paad",
|
||||
"Deleted": "Fuortsmiten",
|
||||
"Deselect All": "Alles Deselektearje",
|
||||
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
|
||||
"Deselect devices to stop sharing this folder with.": "Kies de apparaten om dizze map net langer mei te dielen.",
|
||||
"Device": "Apparaat",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Apparaat \"{{name}}\" {{device}} op ({{address}}) wol ferbining meitsje. Nij apparaat taheakje?",
|
||||
"Device ID": "Apparaat-ID",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Periodic scanning útskeakele en it ynskeakeljen fan it yn'e gaten hâlden fan feroarings is mislearre, wurd eltse 1m opnij besocht:",
|
||||
"Discard": "Fuortsmite\n",
|
||||
"Disconnected": "Ferbining ferbrutsen",
|
||||
"Disconnected (Unused)": "Ferbining ferbrutsen (Net Brûkt)",
|
||||
"Discovered": "Untdekt",
|
||||
"Discovery": "Untdekking",
|
||||
"Discovery Failures": "Untdekkingsflaters",
|
||||
@@ -106,7 +108,7 @@
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Fier troch komma's skieden (\"tcp://ip:port\", \"tcp://host:port\") adressen yn of \"dynamic\" om automatyske ûntdekking fan it adres út te fieren.",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Fier troch komma's skieden (\"tcp://ip:port\", \"tcp://host:port\") adressen yn of \"dynamic\" om automatyske ûntdekking fan it adres út te fieren.",
|
||||
"Enter ignore patterns, one per line.": "Fier negearpatroanen yn, ien per rigel.",
|
||||
"Enter up to three octal digits.": "Enter up to three octal digits.",
|
||||
"Enter up to three octal digits.": "Fier oant trije oktale nûmers yn.",
|
||||
"Error": "Flater",
|
||||
"External File Versioning": "Ekstern ferzjebehear foar triemen",
|
||||
"Failed Items": "Mislearre items",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Yntrodusearrer",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Dizze betingst omkeare (d.w.z. net útslute) ",
|
||||
"Keep Versions": "Ferzjes bewarje",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Grutste earst",
|
||||
"Last File Received": "Leste triem ûntfongen",
|
||||
"Last Scan": "Lêst Skent",
|
||||
@@ -172,7 +175,7 @@
|
||||
"Listeners": "Harkers",
|
||||
"Loading data...": "Data oan it laden...",
|
||||
"Loading...": "Oan it laden...",
|
||||
"Local Additions": "Local Additions",
|
||||
"Local Additions": "Lokale Tafoegingen",
|
||||
"Local Discovery": "Lokale ûntdekking",
|
||||
"Local State": "Lokale tastân",
|
||||
"Local State (Total)": "Lokale tastân (Folledich)",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Skoftsje",
|
||||
"Pause All": "Alles skoftsje",
|
||||
"Paused": "Skoftet",
|
||||
"Paused (Unused)": "Pausearre (Net Brûkt)",
|
||||
"Pending changes": "Wachtet op feroarings",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodic scanning op opjûn ynterfal en feroarings wurde net yn'e gaten hâlden.",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodic scanning op opjûn ynterfal en feroarings wurde yn'e gaten hâlden.",
|
||||
@@ -229,7 +233,7 @@
|
||||
"Please wait": "In amerijke",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefiks dy't oanjout dat de triem fourtsmiten wurde kin wannear dit it ferwiderjen belet.",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefiks dy't oanjout dat fergelykings mei it patroans net haadlettergefoelich wêze sille.",
|
||||
"Preparing to Sync": "Preparing to Sync",
|
||||
"Preparing to Sync": "Tarieden om te Synchronisearren",
|
||||
"Preview": "Foarbyld",
|
||||
"Preview Usage Report": "Foarbyld fan brûkensrapport ",
|
||||
"Quick guide to supported patterns": "Fluch-paadwizer foar stipe patroanen",
|
||||
@@ -266,7 +270,7 @@
|
||||
"See external versioning help for supported templated command line parameters.": "Sjoch de eksterne help fan fersjebehearder foar stipe foarbylden fan kommando-rige-parameters.",
|
||||
"Select All": "Alles Selektearje",
|
||||
"Select a version": "Kies in ferzje",
|
||||
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
|
||||
"Select additional devices to share this folder with.": "Doch apparaten derby om dizze map mei te dielen.",
|
||||
"Select latest version": "Selektearje de nijste ferzje",
|
||||
"Select oldest version": "Selektearje de âldste ferzje",
|
||||
"Select the devices to share this folder with.": "Sykje de apparaten út om dizze map mei te dielen.",
|
||||
@@ -339,7 +343,7 @@
|
||||
"The path cannot be blank.": "It paad mei net leech wêze.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "It fluggenslimyt moat in posityf nûmer wêze (0: gjin limyt)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "It wersken-ynterfal moat in posityf tal fan sekonden wêze.",
|
||||
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
|
||||
"There are no devices to share this folder with.": "Der binne gjin apparaten om dizze map mei te dielen.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "Sy wurde automatysk opnij probearre en sille syngronisearre wurde wannear at de flater oplost is.",
|
||||
"This Device": "Dit Apparaat",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Dit kin samar ynkringers (hackers) tagong jaan om elke triem op jo kompjûter te besjen en te feroarjen.",
|
||||
@@ -349,14 +353,14 @@
|
||||
"Time the item was last modified": "Tiidstip dat it ûnderdiel foar it lest oanpast waard.",
|
||||
"Trash Can File Versioning": "Jiskefet-triemferzjebehear",
|
||||
"Type": "Type",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"UNIX Permissions": "UNIX-Rjochten",
|
||||
"Unavailable": "Net beskikber",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Net beskikber/Utsetten troch administrator of ûnderhâlder",
|
||||
"Undecided (will prompt)": "Noch net beslist (wurd noch frege)",
|
||||
"Unignore": "Net mear negeare",
|
||||
"Unknown": "Unbekend",
|
||||
"Unshared": "Net dielt",
|
||||
"Unshared Devices": "Unshared Devices",
|
||||
"Unshared Devices": "Net-dielde Apparaten",
|
||||
"Unused": "Net brûkt",
|
||||
"Up to Date": "By de tiid",
|
||||
"Updated": "Fernijt",
|
||||
@@ -374,8 +378,8 @@
|
||||
"Versions": "Ferzjes",
|
||||
"Versions Path": "Ferzjes-paad",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Ferzjes wurde automatysk fuortsmiten wannear't se âlder binne dan de maksimale âldens of wannear it tal fan triemen yn in ynterval grutter is dan tastean.",
|
||||
"Waiting to Scan": "Waiting to Scan",
|
||||
"Waiting to Sync": "Waiting to Sync",
|
||||
"Waiting to Scan": "Wachtet om te Skennen",
|
||||
"Waiting to Sync": "Wachten om te Synchronisearren",
|
||||
"Waiting to scan": "Wachtet om te skennen",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warskôging, dit paad is in boppelizzende triemtafel fan in besteande map \"{{otherFolder}}\".",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warskôging, dit paad is in boppelizzende triemtafel fan in besteande map \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"Are you sure you want to remove device {%name%}?": "Biztos, hogy el akarod távolítani az eszközt: {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Biztos, hogy el akarod távolítani a mappát: {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Biztos, hogy vissza akarod állítani a(z) {{count}} fájlt?",
|
||||
"Are you sure you want to upgrade?": "Valóban frissíthető?",
|
||||
"Are you sure you want to upgrade?": "Biztos, hogy frissíteni akarod?",
|
||||
"Auto Accept": "Automatikus elfogadás",
|
||||
"Automatic Crash Reporting": "Automatikus összeomlás-jelentés",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Az automatikus frissítés most lehetőséget kínál a stabil és az előzetes kiadások közötti választásra.",
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Megjegyzés, a sor elején használva",
|
||||
"Compression": "Tömörítés",
|
||||
"Configured": "Beállított",
|
||||
"Connected (Unused)": "Kapcsolódva (használaton kívül)",
|
||||
"Connection Error": "Kapcsolódási hiba",
|
||||
"Connection Type": "Kapcsolattípus",
|
||||
"Connections": "Kapcsolatok",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "A periodikus átnézés letiltva és a változások keresésének beállítása sikertelen, 1 percenként újrapróbálkozás:",
|
||||
"Discard": "Elvetés",
|
||||
"Disconnected": "Kapcsolat bontva",
|
||||
"Disconnected (Unused)": "Kapcsolat bontva (használaton kívül)",
|
||||
"Discovered": "Felfedezett",
|
||||
"Discovery": "Felfedezés",
|
||||
"Discovery Failures": "Felfedezési hibák",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Bevezető",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "A feltétel ellentéte (pl. ki nem hagyás)",
|
||||
"Keep Versions": "Megtartott verziók",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Nagyobb először",
|
||||
"Last File Received": "Utolsó beérkezett fájl",
|
||||
"Last Scan": "Utolsó vizsgálat",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Szünet",
|
||||
"Pause All": "Mindent szüneteltet",
|
||||
"Paused": "Szünetel",
|
||||
"Paused (Unused)": "Szüneteltetve (használaton kívül)",
|
||||
"Pending changes": "Várakozó módosítások",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodikus átnézés a megadott időközönként és a változások keresése letiltva",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodikus átnézés a megadott időközönként és a változások keresése engedélyezve",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Per commentare, va inserito all'inizio di una riga",
|
||||
"Compression": "Compressione",
|
||||
"Configured": "Configurato",
|
||||
"Connected (Unused)": "Connesso (non utilizzato)",
|
||||
"Connection Error": "Errore di Connessione",
|
||||
"Connection Type": "Tipo di Connessione",
|
||||
"Connections": "Connessioni",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Scansione periodica disabilitata e configurazione fallita del monitoraggio cambiamenti, nuovo tentativo ogni 1m:",
|
||||
"Discard": "Scartare",
|
||||
"Disconnected": "Disconnesso",
|
||||
"Disconnected (Unused)": "Disconnesso (non utilizzato)",
|
||||
"Discovered": "Individuato",
|
||||
"Discovery": "Individuazione",
|
||||
"Discovery Failures": "Individuazione Fallita",
|
||||
@@ -106,7 +108,7 @@
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Inserisci indirizzi separati da virgola (\"tcp://ip:porta\", \"tcp://host:porta\") oppure \"dynamic\" per effettuare il rilevamento automatico dell'indirizzo.",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Inserire gli indirizzi separati da virgola (\"tcp://ip:porta\", \"tcp://host:porta\") o \"dynamic\" per eseguire il rilevamento automatico dell'indirizzo.",
|
||||
"Enter ignore patterns, one per line.": "Inserisci gli schemi di esclusione, uno per riga.",
|
||||
"Enter up to three octal digits.": "Enter up to three octal digits.",
|
||||
"Enter up to three octal digits.": "Immetti fino a tre cifre ottali.",
|
||||
"Error": "Errore",
|
||||
"External File Versioning": "Controllo Versione Esterno",
|
||||
"Failed Items": "Elementi Errati",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Introduttore",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversione della condizione indicata (ad es. non escludere)",
|
||||
"Keep Versions": "Versioni Mantenute",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Prima il più grande",
|
||||
"Last File Received": "Ultimo File Ricevuto",
|
||||
"Last Scan": "Ultima Scansione",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pausa",
|
||||
"Pause All": "Pausa Tutti",
|
||||
"Paused": "In Pausa",
|
||||
"Paused (Unused)": "In pausa (non utilizzato)",
|
||||
"Pending changes": "Modifiche in attesa",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Scansione periodica a intervalli determinati e monitoraggio cambiamenti disabilitata",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Scansione periodica a intervalli determinati e monitoraggio cambiamenti abilitata",
|
||||
@@ -349,7 +353,7 @@
|
||||
"Time the item was last modified": "Ora dell'ultima modifica degli elementi",
|
||||
"Trash Can File Versioning": "Controllo Versione con Cestino",
|
||||
"Type": "Tipo",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"UNIX Permissions": "Permessi UNIX",
|
||||
"Unavailable": "Non disponibile",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Non disponibile/Disabilitato dall'amministratore o dal manutentore",
|
||||
"Undecided (will prompt)": "Non deciso (verrà richiesto)",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"Are you sure you want to restore {%count%} files?": "Are you sure you want to restore {{count}} files?",
|
||||
"Are you sure you want to upgrade?": "アップグレードしてよろしいですか?",
|
||||
"Auto Accept": "自動承諾",
|
||||
"Automatic Crash Reporting": "Automatic Crash Reporting",
|
||||
"Automatic Crash Reporting": "自動クラッシュレポート",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "自動アップグレードは、安定版とリリース候補版のいずれかを選べるようになりました。",
|
||||
"Automatic upgrades": "自動アップグレード",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Automatic upgrades are always enabled for candidate releases.",
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "行頭で使用するとコメント行になります",
|
||||
"Compression": "圧縮",
|
||||
"Configured": "設定値",
|
||||
"Connected (Unused)": "接続中 (未使用)",
|
||||
"Connection Error": "接続エラー",
|
||||
"Connection Type": "接続種別",
|
||||
"Connections": "接続",
|
||||
@@ -75,13 +76,14 @@
|
||||
"Device rate limits": "デバイス速度制限",
|
||||
"Device that last modified the item": "Device that last modified the item",
|
||||
"Devices": "デバイス",
|
||||
"Disable Crash Reporting": "Disable Crash Reporting",
|
||||
"Disable Crash Reporting": "クラッシュレポートを無効にする",
|
||||
"Disabled": "無効",
|
||||
"Disabled periodic scanning and disabled watching for changes": "定期スキャンと変更の監視はいずれも無効です",
|
||||
"Disabled periodic scanning and enabled watching for changes": "定期スキャンは無効で変更の監視は有効です",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:",
|
||||
"Discard": "破棄",
|
||||
"Disconnected": "切断中",
|
||||
"Disconnected (Unused)": "切断中 (未使用)",
|
||||
"Discovered": "探索結果",
|
||||
"Discovery": "探索サーバー",
|
||||
"Discovery Failures": "探索サーバーへの接続失敗",
|
||||
@@ -97,7 +99,7 @@
|
||||
"Edit Folder": "フォルダーの編集",
|
||||
"Editing": "編集中",
|
||||
"Editing {%path%}.": "{{path}} を編集中",
|
||||
"Enable Crash Reporting": "Enable Crash Reporting",
|
||||
"Enable Crash Reporting": "クラッシュレポートを有効にする",
|
||||
"Enable NAT traversal": "NATトラバーサルを有効にする",
|
||||
"Enable Relaying": "中継サーバー経由の通信を有効にする",
|
||||
"Enabled": "有効",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "紹介者デバイス",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "条件の否定 (つまり、無視しないという意味になります)",
|
||||
"Keep Versions": "保持するバージョン数",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "大きい順",
|
||||
"Last File Received": "最後に受信したファイル",
|
||||
"Last Scan": "最終スキャン日時",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "一時停止",
|
||||
"Pause All": "すべて一時停止",
|
||||
"Paused": "一時停止中",
|
||||
"Paused (Unused)": "一時停止中 (未使用)",
|
||||
"Pending changes": "保留中の変更",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "定期スキャンは有効で変更の監視は無効です",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "定期スキャンと変更の監視はいずれも有効です",
|
||||
@@ -258,7 +262,7 @@
|
||||
"Resume All": "すべて再開",
|
||||
"Reused": "中断後再利用",
|
||||
"Revert Local Changes": "Revert Local Changes",
|
||||
"Running": "Running",
|
||||
"Running": "実行中",
|
||||
"Save": "保存",
|
||||
"Scan Time Remaining": "スキャン残り時間",
|
||||
"Scanning": "スキャン中",
|
||||
@@ -310,7 +314,7 @@
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthingはフリーでオープンソースのソフトウェアであり、ライセンスは MPL v2.0 です。",
|
||||
"Syncthing is restarting.": "Syncthingを再起動しています。",
|
||||
"Syncthing is upgrading.": "Syncthingをアップグレード中です。",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing は、開発者にクラッシュに関する情報を自動的に報告することができます。この機能はデフォルトで有効になっています。",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthingが落ちているか、インターネット接続に問題があります。リトライ中です…",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "リクエストの処理に問題があるようです。問題が継続する場合、ページを更新するかSyncthingを再起動してください。",
|
||||
"Take me back": "キャンセル",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "명령행에서 시작을 할수 있어요.",
|
||||
"Compression": "압축",
|
||||
"Configured": "설정됨",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "연결 에러",
|
||||
"Connection Type": "연결 종류",
|
||||
"Connections": "연결",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:",
|
||||
"Discard": "Discard",
|
||||
"Disconnected": "연결 끊김",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "탐색됨",
|
||||
"Discovery": "탐색",
|
||||
"Discovery Failures": "탐색 실패",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "유도",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "주어진 조건의 반대 (전혀 배제하지 않음)",
|
||||
"Keep Versions": "버전 보관",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "큰 파일 순",
|
||||
"Last File Received": "마지막으로 받은 파일",
|
||||
"Last Scan": "마지막 탐색",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "일시 중지",
|
||||
"Pause All": "모두 일시 중지",
|
||||
"Paused": "일시 중지됨",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Pending changes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodic scanning at given interval and disabled watching for changes",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodic scanning at given interval and enabled watching for changes",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Komentaras naudojamas naujoje eilutėje",
|
||||
"Compression": "Kompresija",
|
||||
"Configured": "Sukonfigūruotas",
|
||||
"Connected (Unused)": "Prisijungęs (Nenaudojamas)",
|
||||
"Connection Error": "Susijungimo klaida",
|
||||
"Connection Type": "Ryšio tipas",
|
||||
"Connections": "Ryšiai",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Išjungtas periodinis nuskaitymas ir nepavykęs nustatyti pakeitimų stebėjimas, bandoma iš naujo kas 1 min.:",
|
||||
"Discard": "Atmesti",
|
||||
"Disconnected": "Atsijungęs",
|
||||
"Disconnected (Unused)": "Atsijungęs (Nenaudojamas)",
|
||||
"Discovered": "Atrastas",
|
||||
"Discovery": "Lokacija",
|
||||
"Discovery Failures": "Matomumo nesėkmės",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Supažindintojas",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Apversti sąlygas (pvz.: nenustoti naudoti)",
|
||||
"Keep Versions": "Saugojamų versijų kiekis",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Didžiausi pirmiau",
|
||||
"Last File Received": "Paskutinis priimtas failas",
|
||||
"Last Scan": "Paskutinis nuskaitymas",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pristabdyti",
|
||||
"Pause All": "Pristabdyti visus",
|
||||
"Paused": "Pristabdyta",
|
||||
"Paused (Unused)": "Pristabdytas (Nenaudojamas)",
|
||||
"Pending changes": "Laukiantys pakeitimai",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodinis nuskaitymas nurodytu intervalu ir išjungtas pakeitimų stebėjimas",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodinis nuskaitymas nurodytu intervalu ir įjungtas pakeitimų stebėjimas",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Kommentar, når det blir brukt i starten av en linje.",
|
||||
"Compression": "Komprimering",
|
||||
"Configured": "Oppsatt",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Tilkoblingsfeil",
|
||||
"Connection Type": "Tilkoblingstype",
|
||||
"Connections": "Tilkoblinger",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Skrudde av periodisk skanning og mislyktes i oppsett av oppsyn med endringer, prøver igjen hvert minutt:",
|
||||
"Discard": "Kasser",
|
||||
"Disconnected": "Frakoblet",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Oppdaget",
|
||||
"Discovery": "Oppslag",
|
||||
"Discovery Failures": "Oppslagsfeil",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Introduktør",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Invers av den gitte tilstanden (dvs. ekskluder ikke)",
|
||||
"Keep Versions": "Behold versjoner",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Største fil først",
|
||||
"Last File Received": "Sist mottatte fil",
|
||||
"Last Scan": "Siste gjennomsøking",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Oppholde",
|
||||
"Pause All": "Sett alt på pause",
|
||||
"Paused": "Oppholdt",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Påventende endringer",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodisk skanning på gitte intervaller og avskrudd oppsyn med endringer",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodisk skanning på gitte intervall og påskrudd oppsyn med endringer",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Opmerking, wanneer gebruikt aan het begin van een regel",
|
||||
"Compression": "Compressie",
|
||||
"Configured": "Geconfigureerd",
|
||||
"Connected (Unused)": "Verbonden (niet gebruikt)",
|
||||
"Connection Error": "Verbindingsfout",
|
||||
"Connection Type": "Soort verbinding",
|
||||
"Connections": "Verbindingen",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Periodiek scannen uitgeschakeld en instellen van opvolgen van wijzigingen mislukt. Elke minuut wordt opnieuw geprobeerd:",
|
||||
"Discard": "Verwerpen",
|
||||
"Disconnected": "Niet verbonden",
|
||||
"Disconnected (Unused)": "Niet verbonden (niet gebruikt)",
|
||||
"Discovered": "Ontdekt",
|
||||
"Discovery": "Ontdekking",
|
||||
"Discovery Failures": "Ontdekkingsproblemen",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Introductie-apparaat",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversie van de gegeven voorwaarde (d.w.z. niet uitsluiten)",
|
||||
"Keep Versions": "Versies behouden",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Grootste eerst",
|
||||
"Last File Received": "Laatst ontvangen bestand",
|
||||
"Last Scan": "Laatste scan",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pauzeren",
|
||||
"Pause All": "Alles pauzeren",
|
||||
"Paused": "Gepauzeerd",
|
||||
"Paused (Unused)": "Gepauzeerd (niet gebruikt)",
|
||||
"Pending changes": "Wijzigingen in afwachting",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodiek scannen met opgegeven interval; opvolgen van wijzigingen uitgeschakeld",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodiek scannen met opgegeven interval; opvolgen van wijzigingen ingeschakeld",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Komentarz, jeżeli użyty na początku linii",
|
||||
"Compression": "Kompresja",
|
||||
"Configured": "Skonfigurowane",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Błąd połączenia",
|
||||
"Connection Type": "Rodzaj połączenia",
|
||||
"Connections": "Połączenia",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Wyłączono okresowe skanowanie i nie udało się skonfigurować obserwowania zmian, powtórzę co minutę:",
|
||||
"Discard": "Odrzuć",
|
||||
"Disconnected": "Rozłączony",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Odkryte",
|
||||
"Discovery": "Odnajdywanie",
|
||||
"Discovery Failures": "Błędy odnajdowania",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Wprowadzający",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Odwrócenie podanego wzorca (np. nie wykluczaj)",
|
||||
"Keep Versions": "Zachowuj wersje",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Największe na początku",
|
||||
"Last File Received": "Ostatni otrzymany plik",
|
||||
"Last Scan": "Czas ostatniego skanu",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Zatrzymaj",
|
||||
"Pause All": "Zatrzymaj wszystkie",
|
||||
"Paused": "Zatrzymany",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Oczekujące zmiany",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Okresowe skanowanie w podanym przedziale czasu i wyłączone obserwowanie zmian",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Okresowe skanowanie w podanym przedziale czasu i włączone obserwowanie zmian",
|
||||
|
||||
@@ -28,12 +28,12 @@
|
||||
"Anonymous Usage Reporting": "Relatórios anônimos de uso",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "O formato do relatório anônimo de uso mudou. Gostaria de usar o formato novo?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Quaisquer dispositivos configurados em um apresentador também serão adicionados a este dispositivo.",
|
||||
"Are you sure you want to remove device {%name%}?": "Tem certeza de que deseja remover o dispositivo {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Tem certeza de que deseja remover a pasta {{name}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Tem certeza de que deseja restaurar {{count}} arquivo(s)?",
|
||||
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
|
||||
"Are you sure you want to remove device {%name%}?": "Deseja mesmo remover o dispositivo {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Deseja mesmo remover a pasta {{name}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Deseja mesmo restaurar {{count}} arquivo(s)?",
|
||||
"Are you sure you want to upgrade?": "Deseja mesmo fazer a atualização?",
|
||||
"Auto Accept": "Aceitar automaticamente",
|
||||
"Automatic Crash Reporting": "Automatic Crash Reporting",
|
||||
"Automatic Crash Reporting": "Relatório automático de falhas",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "A atualização automática agora oferece a escolha entre versões estáveis e candidatas ao lançamento.",
|
||||
"Automatic upgrades": "Atualizações automáticas",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Automatic upgrades are always enabled for candidate releases.",
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Comentário, se usado no início de uma linha",
|
||||
"Compression": "Compressão",
|
||||
"Configured": "Configurado",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Erro de conexão",
|
||||
"Connection Type": "Tipo da conexão",
|
||||
"Connections": "Conexões",
|
||||
@@ -58,9 +59,9 @@
|
||||
"Copied from original": "Copiado do original",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Direitos reservados © 2014-2016 aos seguintes colaboradores:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 dos seguintes Colaboradores:",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 the following Contributors:",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 dos Contribuintes:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Criando filtros, sobrescrevendo o arquivo {{path}}.",
|
||||
"Currently Shared With Devices": "Currently Shared With Devices",
|
||||
"Currently Shared With Devices": "Compartilhado com outros dispositivos",
|
||||
"Danger!": "Perigo!",
|
||||
"Debugging Facilities": "Facilidades de depuração",
|
||||
"Default Folder Path": "Caminho padrão da pasta",
|
||||
@@ -75,13 +76,14 @@
|
||||
"Device rate limits": "Device rate limits",
|
||||
"Device that last modified the item": "Dispositivo que modificou o item pela última vez",
|
||||
"Devices": "Dispositivos",
|
||||
"Disable Crash Reporting": "Disable Crash Reporting",
|
||||
"Disable Crash Reporting": "Desabilitar relatório de falhas",
|
||||
"Disabled": "Desabilitado",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Verificação periódica e verificação automática de mudanças desabilitadas",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Verificação periódica desabilitada. Verificação automática de mudanças habilitada.",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Verificação periódica desabilitada. Não foi possível configurar a verificação automática de mudanças, tentando novamente a cada 1 minuto:",
|
||||
"Discard": "Discard",
|
||||
"Discard": "Descartar",
|
||||
"Disconnected": "Desconectado",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Descoberto",
|
||||
"Discovery": "Descoberta",
|
||||
"Discovery Failures": "Falhas na descoberta",
|
||||
@@ -97,7 +99,7 @@
|
||||
"Edit Folder": "Editar pasta",
|
||||
"Editing": "Editando",
|
||||
"Editing {%path%}.": "Editando {{path}}.",
|
||||
"Enable Crash Reporting": "Enable Crash Reporting",
|
||||
"Enable Crash Reporting": "Habilitar relatório de falhas",
|
||||
"Enable NAT traversal": "Habilitar NAT",
|
||||
"Enable Relaying": "Habilitar retransmissão",
|
||||
"Enabled": "Habilitado",
|
||||
@@ -152,15 +154,16 @@
|
||||
"Ignore": "Ignorar",
|
||||
"Ignore Patterns": "Filtros",
|
||||
"Ignore Permissions": "Ignorar permissões",
|
||||
"Ignored Devices": "Ignored Devices",
|
||||
"Ignored Folders": "Ignored Folders",
|
||||
"Ignored at": "Ignored at",
|
||||
"Ignored Devices": "Dispositivos ignorados",
|
||||
"Ignored Folders": "Pastas ignoradas",
|
||||
"Ignored at": "Ignorada em",
|
||||
"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.",
|
||||
"Introduced By": "Introduzido por",
|
||||
"Introducer": "Apresentador",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversão de uma condição (ou seja, não excluir)",
|
||||
"Keep Versions": "Manter versões",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Maior primeiro",
|
||||
"Last File Received": "Último arquivo recebido",
|
||||
"Last Scan": "Última verificação",
|
||||
@@ -168,15 +171,15 @@
|
||||
"Later": "Depois",
|
||||
"Latest Change": "Última mudança",
|
||||
"Learn more": "Saiba mais",
|
||||
"Limit": "Limit",
|
||||
"Limit": "Limite",
|
||||
"Listeners": "Escutadores",
|
||||
"Loading data...": "Carregando dados...",
|
||||
"Loading...": "Carregando",
|
||||
"Local Additions": "Local Additions",
|
||||
"Local Additions": "Acréscimos locais",
|
||||
"Local Discovery": "Descoberta local",
|
||||
"Local State": "Estado local",
|
||||
"Local State (Total)": "Estado local (total)",
|
||||
"Locally Changed Items": "Locally Changed Items",
|
||||
"Locally Changed Items": "Itens modificados localmente",
|
||||
"Log": "Log",
|
||||
"Log tailing paused. Click here to continue.": "Observação do log pausada. Clique aqui para continuar.",
|
||||
"Log tailing paused. Scroll to bottom continue.": "Log tailing paused. Scroll to bottom continue.",
|
||||
@@ -219,7 +222,8 @@
|
||||
"Pause": "Pausar",
|
||||
"Pause All": "Pausar todas",
|
||||
"Paused": "Em pausa",
|
||||
"Pending changes": "Pending changes",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Modificações pendentes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Verificação periódica habilitada no intervalo escolhido. Verificação automática de mudanças desabilitada",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Verificação periódica habilitada no intervalo escolhido. Verificação automática de mudanças habilitada",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Verificação periódica habilitada no intervalo escolhido. Não foi possível configurar a verificação automática de mudanças, tentando novamente a cada 1 minuto:",
|
||||
@@ -229,7 +233,7 @@
|
||||
"Please wait": "Aguarde",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefixo indicando que o arquivo pode ser removido caso esteja impedindo a remoção do seu diretório",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefixo indicando que o filtro deve ser igualado sem distinção entre maiúsculas e minúsculas",
|
||||
"Preparing to Sync": "Preparing to Sync",
|
||||
"Preparing to Sync": "Preparando para sincronizar",
|
||||
"Preview": "Visualizar",
|
||||
"Preview Usage Report": "Visualizar relatório de uso",
|
||||
"Quick guide to supported patterns": "Guia rápido dos padrões suportados",
|
||||
@@ -257,16 +261,16 @@
|
||||
"Resume": "Resumir",
|
||||
"Resume All": "Resumir Todas",
|
||||
"Reused": "Reutilizado",
|
||||
"Revert Local Changes": "Revert Local Changes",
|
||||
"Revert Local Changes": "Reverter mudanças locais",
|
||||
"Running": "Rodando",
|
||||
"Save": "Salvar",
|
||||
"Scan Time Remaining": "Tempo de verificação restante",
|
||||
"Scanning": "Verificando",
|
||||
"See external versioner help for supported templated command line parameters.": "Consulte a ajuda sobre versionamento externo para modelos de parâmetros de linha de comando aceitos.",
|
||||
"See external versioning help for supported templated command line parameters.": "Consulte a ajuda sobre versionamento externo para modelos de parâmetros de linha de comando aceitos.",
|
||||
"Select All": "Select All",
|
||||
"Select All": "Selecionar tudo",
|
||||
"Select a version": "Selecione uma versão",
|
||||
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
|
||||
"Select additional devices to share this folder with.": "Selecione outros dispositivos com os quais a pasta será compartilhada.",
|
||||
"Select latest version": "Escolher a última versão",
|
||||
"Select oldest version": "Escolher a versão mais antiga",
|
||||
"Select the devices to share this folder with.": "Selecione os dispositivos com os quais esta pasta será compartilhada.",
|
||||
@@ -307,7 +311,7 @@
|
||||
"Syncing": "Sincronizando",
|
||||
"Syncthing has been shut down.": "O Syncthing foi desligado.",
|
||||
"Syncthing includes the following software or portions thereof:": "O Syncthing inclui os seguintes programas ou partes deles:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing is Free and Open Source Software licensed as MPL v2.0.",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "O Syncthing é um software de código aberto licenciado pela MPL v2.0.",
|
||||
"Syncthing is restarting.": "O Syncthing está sendo reiniciado.",
|
||||
"Syncthing is upgrading.": "O Syncthing está sendo atualizado.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.",
|
||||
@@ -381,7 +385,7 @@
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Aviso: este caminho é o diretório pai da pasta \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Atenção, este caminho é um subdiretório de uma pasta já existente: \"{{otherFolder}}\".",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Aviso: este caminho é um subdiretório da pasta \"{{otherFolderLabel}}\" ({{otherFolder}})",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Warning: If you are using an external watcher like {{syncthingInotify}}, you should make sure it is deactivated.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Aviso: caso você esteja usando um observador externo como o {{syncthingInotify}}, tenha certeza de que ele está desativado.",
|
||||
"Watch for Changes": "Observar alterações",
|
||||
"Watching for Changes": "Observando alterações",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Watching for changes discovers most changes without periodic scanning.",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Comentário, quando usado no início de uma linha",
|
||||
"Compression": "Compressão",
|
||||
"Configured": "Configurado",
|
||||
"Connected (Unused)": "Ligado (não usado)",
|
||||
"Connection Error": "Erro de ligação",
|
||||
"Connection Type": "Tipo de ligação",
|
||||
"Connections": "Ligações",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Desactivada a verificação periódica e falha ao preparar a vigilância de alterações, tentando novamente a cada minuto:",
|
||||
"Discard": "Descartar",
|
||||
"Disconnected": "Desconectado",
|
||||
"Disconnected (Unused)": "Desligado (não usado)",
|
||||
"Discovered": "Descoberto",
|
||||
"Discovery": "Pesquisa",
|
||||
"Discovery Failures": "Falhas da pesquisa",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Apresentador",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversão de uma dada condição (ou seja, não excluir)",
|
||||
"Keep Versions": "Manter versões",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Primeiro os maiores",
|
||||
"Last File Received": "Último ficheiro recebido",
|
||||
"Last Scan": "Última verificação",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pausar",
|
||||
"Pause All": "Pausar todas",
|
||||
"Paused": "Em pausa",
|
||||
"Paused (Unused)": "Em pausa (não usado)",
|
||||
"Pending changes": "Alterações pendentes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Verificação periódica no intervalo dado e desactivada a vigilância de alterações",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Verificação periódica no intervalo dado e activada a vigilância de alterações",
|
||||
@@ -310,7 +314,7 @@
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing é Software Livre e de Código Aberto licenciado como MPL v2.0.",
|
||||
"Syncthing is restarting.": "O Syncthing está a reiniciar.",
|
||||
"Syncthing is upgrading.": "O Syncthing está a actualizar-se.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "O Syncthing agora suporta o envio automático de relatórios de estouros para os programadores. Esta funcionalidade vem inicialmente activada.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "O Syncthing agora suporta o envio automático de relatórios de estouro para os programadores. Esta funcionalidade vem inicialmente activada.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "O Syncthing parece estar em baixo, ou então existe um problema com a sua ligação à Internet. Tentando novamente...",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "O Syncthing parece estar com problemas em processar o seu pedido. Tente recarregar a página ou reiniciar o Syncthing, se o problema persistir.",
|
||||
"Take me back": "Voltar atrás",
|
||||
@@ -374,8 +378,8 @@
|
||||
"Versions": "Versões",
|
||||
"Versions Path": "Caminho das versões",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "As versões são eliminadas automaticamente se forem mais antigas do que a idade máxima ou excederem o número máximo de ficheiros permitido num intervalo.",
|
||||
"Waiting to Scan": "À espera para verificar",
|
||||
"Waiting to Sync": "À espera para sincronizar",
|
||||
"Waiting to Scan": "Aguardando a verificação",
|
||||
"Waiting to Sync": "Aguardando a sincronização",
|
||||
"Waiting to scan": "À espera para verificar",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Aviso: Este caminho é uma pasta mãe duma pasta \"{{otherFolder}}\" já existente.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Aviso: Este caminho é uma pasta mãe duma pasta \"{{otherFolderLabel}}\" ({{otherFolder}}) já existente.",
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
"Are you sure you want to remove device {%name%}?": "Вы уверены, что хотите удалить устройство {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Вы уверены, что хотите удалить папку {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Вы уверены, что хотите восстановить {{count}} файлов?",
|
||||
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
|
||||
"Are you sure you want to upgrade?": "Вы уверены, что хотите обновить?",
|
||||
"Auto Accept": "Автопринятие",
|
||||
"Automatic Crash Reporting": "Automatic Crash Reporting",
|
||||
"Automatic Crash Reporting": "Автоматическая отправка отчётов о сбоях",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Автоматическое обновление теперь предлагает выбор между стабильными выпусками и кандидатами в релизы.",
|
||||
"Automatic upgrades": "Автообновление",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Автоматическое обновление всегда включено для кандидатов в релизы.",
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Комментарий, если используется в начале строки",
|
||||
"Compression": "Сжатие",
|
||||
"Configured": "Сконфигурировано",
|
||||
"Connected (Unused)": "Подключено (не используется)",
|
||||
"Connection Error": "Ошибка подключения",
|
||||
"Connection Type": "Тип соединения",
|
||||
"Connections": "Подключения",
|
||||
@@ -58,15 +59,15 @@
|
||||
"Copied from original": "Скопировано с оригинала",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Авторские права © 2014–2016 принадлежат:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Авторские права © 2014—2017 следующие участники:",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Авторские права © 2014–2019 принадлежат:",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Авторские права © 2014-2019 принадлежат:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Создание шаблонов игнорирования, существующий файл {{path}} будет перезаписан.",
|
||||
"Currently Shared With Devices": "Currently Shared With Devices",
|
||||
"Currently Shared With Devices": "В настоящее время используется совместно с устройствами",
|
||||
"Danger!": "Опасно!",
|
||||
"Debugging Facilities": "Средства отладки",
|
||||
"Default Folder Path": "Путь для папок",
|
||||
"Deleted": "Удалено",
|
||||
"Deselect All": "Снять выделение",
|
||||
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
|
||||
"Deselect devices to stop sharing this folder with.": "Отмените выбор устройств, чтобы прекратить совместное использование этой папки.",
|
||||
"Device": "Устройство",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Устройство «{{name}}» ({{device}} на {{address}}) хочет подключиться. Добавить новое устройство?",
|
||||
"Device ID": "ID устройства",
|
||||
@@ -75,13 +76,14 @@
|
||||
"Device rate limits": "Ограничения скорости для устройства",
|
||||
"Device that last modified the item": "Устройство, последним изменившее объект",
|
||||
"Devices": "Устройства",
|
||||
"Disable Crash Reporting": "Disable Crash Reporting",
|
||||
"Disable Crash Reporting": "Отключить отчёты о сбоях",
|
||||
"Disabled": "Отключено",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Периодическое сканирование и отслеживание изменений отключено",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Периодическое сканирование отключено, отслеживание изменений включено",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Периодическое сканирование отключено, не удалось включить отслеживание изменений, повторная попытка каждую минуту.",
|
||||
"Discard": "Отменить",
|
||||
"Disconnected": "Нет соединения",
|
||||
"Disconnected (Unused)": "Отключено (не используется)",
|
||||
"Discovered": "Обнаружено",
|
||||
"Discovery": "Обнаружение",
|
||||
"Discovery Failures": "Ошибки обнаружения",
|
||||
@@ -97,7 +99,7 @@
|
||||
"Edit Folder": "Редактирование папки",
|
||||
"Editing": "Редактирование",
|
||||
"Editing {%path%}.": "Правка {{path}}.",
|
||||
"Enable Crash Reporting": "Enable Crash Reporting",
|
||||
"Enable Crash Reporting": "Включить отчёты о сбоях",
|
||||
"Enable NAT traversal": "Включить NAT traversal",
|
||||
"Enable Relaying": "Включить релеи",
|
||||
"Enabled": "Включено",
|
||||
@@ -106,7 +108,7 @@
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Введите через запятую («tcp://ip:port», «tcp://host:port») адреса, либо «dynamic», чтобы выполнить автоматическое обнаружение адреса.",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Введите через запятую («tcp://ip:port», «tcp://host:port») адреса, либо «dynamic», чтобы выполнить автоматическое обнаружение адреса.",
|
||||
"Enter ignore patterns, one per line.": "Введите шаблоны игнорирования, по одному на строку.",
|
||||
"Enter up to three octal digits.": "Enter up to three octal digits.",
|
||||
"Enter up to three octal digits.": "Введите до трех восьмеричных цифр.",
|
||||
"Error": "Ошибка",
|
||||
"External File Versioning": "Внешний контроль версий файлов",
|
||||
"Failed Items": "Сбои",
|
||||
@@ -118,7 +120,7 @@
|
||||
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Права на файлы игнорируются при поиске изменений. Используется на файловой системе FAT.",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Когда Syncthing изменяет или удаляет файлы, они помещаются в папку .stversions",
|
||||
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Файлы перемещаются в папку .stversions после их замены или удаления системой Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Когда Syncthing изменяет или удаляет файлы, их версии с таймштампами помещаются в папку .stversions",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Когда Syncthing изменяет или удаляет файлы, их версии с отметками времени помещаются в папку .stversions",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Файлы с временнОй меткой версии помещаются в папку .stversions при их замене или удалении Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Файлы защищены от изменений сделанных на других устройствах, но изменения сделанные на этом устройстве будут отправлены всему кластеру.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Файлы синхронизируются из группы, но изменения, сделанные на этом устройстве, не будут отправлены на другие устройства группы.",
|
||||
@@ -147,8 +149,8 @@
|
||||
"Global Discovery Servers": "Серверы глобального обнаружения",
|
||||
"Global State": "Глобальное состояние",
|
||||
"Help": "Помощь",
|
||||
"Home page": "Домашная страница",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.",
|
||||
"Home page": "Домашняя страница",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Однако, ваши текущие настройки указывают на то, что вы, возможно, не хотите, чтобы эта функция была включена. Мы отключили автоматическую отправку отчетов о сбоях для вас.",
|
||||
"Ignore": "Игнорировать",
|
||||
"Ignore Patterns": "Шаблоны игнорирования",
|
||||
"Ignore Permissions": "Игнорировать файловые права доступа",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Рекомендатель",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Инвертировать текущее условие (например, исключить)",
|
||||
"Keep Versions": "Количество хранимых версий",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Сначала большие",
|
||||
"Last File Received": "Последний полученный файл",
|
||||
"Last Scan": "Последнее сканирование",
|
||||
@@ -172,7 +175,7 @@
|
||||
"Listeners": "Прослушиватель",
|
||||
"Loading data...": "Загрузка данных...",
|
||||
"Loading...": "Загрузка...",
|
||||
"Local Additions": "Local Additions",
|
||||
"Local Additions": "Локальные дополнения",
|
||||
"Local Discovery": "Локальное обнаружение",
|
||||
"Local State": "Локальное состояние",
|
||||
"Local State (Total)": "Локальное состояние (всего)",
|
||||
@@ -219,17 +222,18 @@
|
||||
"Pause": "Пауза",
|
||||
"Pause All": "Приостановить все",
|
||||
"Paused": "Приостановлено",
|
||||
"Paused (Unused)": "Приостановлено (не используется)",
|
||||
"Pending changes": "Несохранённые изменения",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Периодическое сканирование с заданным интервалом, отслеживание изменений отключено",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Периодическое сканирование с заданным интервалом и включено отслеживание изменений",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Периодическое сканирование с заданным интервалом, не удалось включить отслеживание изменений, повторная попытка каждую минуту.",
|
||||
"Permissions": "Разрешения",
|
||||
"Please consult the release notes before performing a major upgrade.": "Перед проведением обновления основной версии ознакомтесь, пожалуйста, с Замечаниями к версии",
|
||||
"Please consult the release notes before performing a major upgrade.": "Перед проведением обновления основной версии ознакомьтесь, пожалуйста, с замечаниями к версии",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Установите имя пользователя и пароль для интерфейса в настройках",
|
||||
"Please wait": "Пожалуйста, подождите",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Префикс указывает, что файл может быть удалён, если он мешает удалить папку",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Префикс указывает, что регистр букв (заглавные/строчные) игнорируется",
|
||||
"Preparing to Sync": "Preparing to Sync",
|
||||
"Preparing to Sync": "Подготовка к синхронизации",
|
||||
"Preview": "Предварительный просмотр",
|
||||
"Preview Usage Report": "Посмотреть отчёт об использовании",
|
||||
"Quick guide to supported patterns": "Краткое руководство по поддерживаемым шаблонам",
|
||||
@@ -266,7 +270,7 @@
|
||||
"See external versioning help for supported templated command line parameters.": "Поддерживаемые шаблонные параметры командной строки см. в документации сторонней программы контроля версий",
|
||||
"Select All": "Выбрать все",
|
||||
"Select a version": "Выберите версию",
|
||||
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
|
||||
"Select additional devices to share this folder with.": "Выберите дополнительные устройства, для которых будет доступна эта папка.",
|
||||
"Select latest version": "Выбрать последнюю версию",
|
||||
"Select oldest version": "Выбрать самую старую версию",
|
||||
"Select the devices to share this folder with.": "Выберите устройства, для которых будет доступна эта папка.",
|
||||
@@ -310,7 +314,7 @@
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing — свободное программное обеспечение с открытым кодом под лицензией MPL v2.0.",
|
||||
"Syncthing is restarting.": "Перезапуск Syncthing.",
|
||||
"Syncthing is upgrading.": "Обновление Syncthing.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing теперь поддерживает автоматическую отправку отчетов о сбоях разработчикам. Эта функция включена по умолчанию.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Кажется, Syncthing не запущен или есть проблемы с подключением к Интернету. Переподключаюсь...",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing столкнулся с проблемой при обработке Вашего запроса. Пожалуйста, обновите страницу или перезапустите Syncthing если проблема повторится.",
|
||||
"Take me back": "Вернуться к редактированию",
|
||||
@@ -339,7 +343,7 @@
|
||||
"The path cannot be blank.": "Путь не может быть пустым.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Скорость должна быть неотрицательным числом (0: нет ограничения)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Интервал пересканирования должен быть неотрицательным количеством секунд.",
|
||||
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
|
||||
"There are no devices to share this folder with.": "Нет устройств, для которых будет доступна эта папка.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "Будут синхронизированы автоматически когда ошибка будет исправлена.",
|
||||
"This Device": "Это устройство",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Это может дать доступ хакерам для чтения и изменения любых файлов на вашем компьютере.",
|
||||
@@ -349,14 +353,14 @@
|
||||
"Time the item was last modified": "Время последней модификации объекта",
|
||||
"Trash Can File Versioning": "Использовать версионность для файлов в Корзине",
|
||||
"Type": "Тип",
|
||||
"UNIX Permissions": "UNIX Permissions",
|
||||
"UNIX Permissions": "Разрешения UNIX",
|
||||
"Unavailable": "Недоступно",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Недоступно или отключено администратором",
|
||||
"Undecided (will prompt)": "Не определено (запрашивать каждый раз)",
|
||||
"Unignore": "Не игнорировать",
|
||||
"Unknown": "Неизвестно",
|
||||
"Unshared": "Необщедоступно",
|
||||
"Unshared Devices": "Unshared Devices",
|
||||
"Unshared Devices": "Устройства без общего доступа",
|
||||
"Unused": "Не используется",
|
||||
"Up to Date": "В актуальном состоянии",
|
||||
"Updated": "Обновлено",
|
||||
@@ -374,8 +378,8 @@
|
||||
"Versions": "Версии",
|
||||
"Versions Path": "Путь к версиям",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Версии удаляются автоматически, если они существуют дольше максимального срока или превышают разрешённое количество файлов за интервал.",
|
||||
"Waiting to Scan": "Waiting to Scan",
|
||||
"Waiting to Sync": "Waiting to Sync",
|
||||
"Waiting to Scan": "Ожидание сканирования",
|
||||
"Waiting to Sync": "Ожидание синхронизации",
|
||||
"Waiting to scan": "Ожидание сканирования",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Внимание! Этот путь — родительская директория уже существующей папки «{{otherFolder}}».",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Внимание! Этот путь — родительская директория уже существующей папки «{{otherFolderLabel}}» ({{otherFolder}}).",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Komentár, keď použité na začiatku riadku",
|
||||
"Compression": "Kompresia",
|
||||
"Configured": "Nakonfigurované",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Chyba pripojenia",
|
||||
"Connection Type": "Typ pripojenia",
|
||||
"Connections": "Spojenia",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:",
|
||||
"Discard": "Zahodiť",
|
||||
"Disconnected": "Odpojené",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Zistené",
|
||||
"Discovery": "Zisťovanie",
|
||||
"Discovery Failures": "Zlyhania zisťovania",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Uvádzač",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inverzia danej podmienky (napr. nevynechať)",
|
||||
"Keep Versions": "Ponechanie verzií",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Najprv najväčšie",
|
||||
"Last File Received": "Posledný prijatý súbor",
|
||||
"Last Scan": "Posledný sken",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Pozastaviť",
|
||||
"Pause All": "Pozastaviť všetky",
|
||||
"Paused": "Pozastavené",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Čakajúce zmeny",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodické skenovanie v zvolenom rozsahu a vypnuté sledovanie zmien.",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodické skenovanie v zvolenom rozsahu a zapnuté sledovanie zmien.",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"A device with that ID is already added.": "En enhet med det ID:t är redan tillagt.",
|
||||
"A device with that ID is already added.": "En enhet med detta ID har redan lagts tillagt.",
|
||||
"A negative number of days doesn't make sense.": "Ett negativt antal dagar är inte rimligt.",
|
||||
"A new major version may not be compatible with previous versions.": "En ny huvudversion kan eventuellt vara inkompatibel med tidigare versioner.",
|
||||
"API Key": "API-nyckel",
|
||||
@@ -18,7 +18,7 @@
|
||||
"Advanced": "Avancerat",
|
||||
"Advanced Configuration": "Avancerad konfiguration",
|
||||
"Advanced settings": "Avancerade inställningar",
|
||||
"All Data": "All data",
|
||||
"All Data": "Alla data",
|
||||
"Allow Anonymous Usage Reporting?": "Tillåt anonym användarstatistiksrapportering?",
|
||||
"Allowed Networks": "Tillåtna nätverk",
|
||||
"Alphabetic": "Alfabetisk",
|
||||
@@ -50,10 +50,11 @@
|
||||
"Comment, when used at the start of a line": "Kommentara, vid användning i början av en rad.",
|
||||
"Compression": "Komprimering",
|
||||
"Configured": "Konfigurerad",
|
||||
"Connected (Unused)": "Ansluten (oanvänd)",
|
||||
"Connection Error": "Anslutningsproblem",
|
||||
"Connection Type": "Anslutningstyp",
|
||||
"Connections": "Anslutningar",
|
||||
"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.": "Kontinuerligt utkik efter ändringar är nu tillgängligt för Syncthing. Detta kommer att upptäcka ändringar på disken och utfärda en skanning på endast de ändrade sökvägarna. Fördelarna är att förändringar sprids snabbare och att mindre fullständiga skanningar krävs.",
|
||||
"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.": "Kontinuerligt bevakning av ändringar är nu tillgängligt inom Syncthing. Detta kommer att upptäcka ändringar på disken och utfärda en skanning på endast de ändrade sökvägarna. Fördelarna är att förändringar sprids snabbare och att mindre fullständiga skanningar krävs.",
|
||||
"Copied from elsewhere": "Kopierat från annanstans",
|
||||
"Copied from original": "Kopierat från original",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 följande bidragare:",
|
||||
@@ -64,7 +65,7 @@
|
||||
"Danger!": "Fara!",
|
||||
"Debugging Facilities": "Felsökningsanläggningar",
|
||||
"Default Folder Path": "Standard mappsökväg",
|
||||
"Deleted": "Raderade",
|
||||
"Deleted": "Borttagna",
|
||||
"Deselect All": "Avmarkera alla",
|
||||
"Deselect devices to stop sharing this folder with.": "Avmarkera enheter för att sluta dela den här mappen med.",
|
||||
"Device": "Enhet",
|
||||
@@ -79,15 +80,16 @@
|
||||
"Disabled": "Inaktiverad",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Inaktiverad periodisk skanning och inaktiverad övervakning av ändringar",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Inaktiverad periodisk skanning och aktiverad övervakning av ändringar",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Inaktiverad periodisk skanning och misslyckades att ställa in övervakning av ändringar, försök igen varje 1m:",
|
||||
"Discard": "Kassera",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Inaktiverad periodisk skanning och misslyckades att ställa in övervakning av ändringar, försöker igen varje 1m:",
|
||||
"Discard": "Kasta",
|
||||
"Disconnected": "Frånkopplad",
|
||||
"Disconnected (Unused)": "Frånkopplad (oanvänd)",
|
||||
"Discovered": "Upptäckt",
|
||||
"Discovery": "Annonsering",
|
||||
"Discovery Failures": "Upptäcktsmisslyckanden",
|
||||
"Do not restore": "Återställ inte",
|
||||
"Do not restore all": "Återställ inte allt",
|
||||
"Do you want to enable watching for changes for all your folders?": "Vill du aktivera håll utkik efter ändringar på alla dina mappar?",
|
||||
"Do you want to enable watching for changes for all your folders?": "Vill du aktivera bevakning av ändringar på alla dina mappar?",
|
||||
"Documentation": "Dokumentation",
|
||||
"Download Rate": "Hämtningshastighet",
|
||||
"Downloaded": "Hämtat",
|
||||
@@ -103,23 +105,23 @@
|
||||
"Enabled": "Aktiverad",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Ange ett icke-negativt antal (t.ex., \"2.35\") och välj en enhet. Procenttalen är som en del av den totala diskstorleken.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Ange ett icke-privilegierat portnummer (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Ange kommaseparerade (\"tcp://ip:port\", \"tcp://host:port\")-adresser eller ordet \"dynamic\" för att använda automatisk uppslagning.",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Ange kommaseparerade adresser (\"tcp://ip:port\", \"tcp://host:port\") eller \"dynamic\" för att utföra automatisk upptäckt av adressen.",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Ange kommaseparerade (\"tcp://ip:port\", \"tcp://host:port\") adresser eller ordet \"dynamic\" för att använda automatisk uppslagning.",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Ange kommaseparerade (\"tcp://ip:port\", \"tcp://host:port\") adresser eller \"dynamic\" för att utföra automatisk upptäckt av adressen.",
|
||||
"Enter ignore patterns, one per line.": "Ange mönster att ignorera, en per rad.",
|
||||
"Enter up to three octal digits.": "Ange upp till tre oktala siffror.",
|
||||
"Error": "Fel",
|
||||
"External File Versioning": "Extern filversionshantering",
|
||||
"Failed Items": "Misslyckade objekt",
|
||||
"Failed to load ignore patterns": "Misslyckades med att ladda ignorera mönster",
|
||||
"Failed to setup, retrying": "Misslyckades med att ställa in, försök igen",
|
||||
"Failed to load ignore patterns": "Det gick inte att läsa in ignorera mönster",
|
||||
"Failed to setup, retrying": "Det gick inte att ställa in, försöker igen",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Misslyckande med att ansluta till IPv6-servrar förväntas om ingen IPv6-anslutning finns.",
|
||||
"File Pull Order": "Filhämtningsprioritering",
|
||||
"File Versioning": "Filversionshantering",
|
||||
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Filrättigheter ignoreras under sökning efter förändringar. Används på FAT-filsystem.",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till .stversions-mappen vid byte eller raderas av Syncthing.",
|
||||
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till .stversions-mappen när de ersätts eller raderas av Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till datumstämplade versioner i en .stversions-mapp när de ersätts eller raderas av Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till datummärkta versioner i en .stversions-mapp när de ersätts eller raderas av Syncthing.",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till .stversions-mappen vid byte eller tas bort av Syncthing.",
|
||||
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till .stversions-mappen när de ersätts eller tas bort av Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till datumstämplade versioner i en .stversions-mapp när de ersätts eller tas bort av Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till datummärkta versioner i en .stversions-mapp när de ersätts eller tas bort av Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Filer skyddas från ändringar gjorda på andra enheter, men ändringar som görs på den här noden skickas till de andra klustermedlemmarna.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Filer synkroniseras från klustret, men alla ändringar som görs lokalt skickas inte till andra enheter.",
|
||||
"Filesystem Notifications": "filsystemsnotifieringar",
|
||||
@@ -133,7 +135,7 @@
|
||||
"Folder Type": "Mapptyp",
|
||||
"Folders": "Mappar",
|
||||
"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.": "För följande mappar uppstod ett fel när du började bevaka ändringar. Det kommer att omförsökas varje minut, så felen kan försvinna snart. Om de fortsätter, försök att åtgärda det underliggande problemet och fråga om hjälp om du inte kan.",
|
||||
"Full Rescan Interval (s)": "Fullständig(a) återkommande skanningsintervall(er)",
|
||||
"Full Rescan Interval (s)": "Fullständig återkommande skanningsintervall (s)",
|
||||
"GUI": "Grafiskt gränssnitt",
|
||||
"GUI Authentication Password": "Gränssnittets autentiseringslösenord",
|
||||
"GUI Authentication User": "Gränssnittets autentiseringsanvändare",
|
||||
@@ -161,17 +163,18 @@
|
||||
"Introducer": "Introduktör",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Inversion av det givna tillståndet (d.v.s. exkluderar inte)",
|
||||
"Keep Versions": "Behåll versioner",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Största först",
|
||||
"Last File Received": "Senaste fil mottagen",
|
||||
"Last Scan": "Senaste skanning",
|
||||
"Last seen": "Senast sedd",
|
||||
"Later": "Senare",
|
||||
"Latest Change": "Senaste ändring",
|
||||
"Learn more": "Ta reda på mer",
|
||||
"Learn more": "Läs mer",
|
||||
"Limit": "Gräns",
|
||||
"Listeners": "Lyssnare",
|
||||
"Loading data...": "Laddar data...",
|
||||
"Loading...": "Laddar...",
|
||||
"Loading data...": "Läser in data...",
|
||||
"Loading...": "Läser in...",
|
||||
"Local Additions": "Lokala tillägg",
|
||||
"Local Discovery": "Lokal annonsering",
|
||||
"Local State": "Lokalt tillstånd",
|
||||
@@ -179,13 +182,13 @@
|
||||
"Locally Changed Items": "Lokalt ändrade objekt",
|
||||
"Log": "Logg",
|
||||
"Log tailing paused. Click here to continue.": "Loggning pausad. Klicka här för att fortsätta.",
|
||||
"Log tailing paused. Scroll to bottom continue.": "Loggning pausad. Rulla till botten för att fortsätta.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Log fortsättning pausad. Bläddra till botten för att fortsätta.",
|
||||
"Log tailing paused. Scroll to bottom continue.": "Loggning pausad. Bläddra till botten för att fortsätta.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Loggning pausad. Bläddra till botten för att fortsätta.",
|
||||
"Logs": "Loggar",
|
||||
"Major Upgrade": "Större uppgradering",
|
||||
"Mass actions": "Massåtgärder",
|
||||
"Master": "Huvud",
|
||||
"Maximum Age": "Maximum ålder",
|
||||
"Maximum Age": "Högsta ålder",
|
||||
"Metadata Only": "Endast metadata",
|
||||
"Minimum Free Disk Space": "Minsta ledigt diskutrymme",
|
||||
"Mod. Device": "Enhet som utförde ändring",
|
||||
@@ -198,7 +201,7 @@
|
||||
"Newest First": "Nyast först",
|
||||
"No": "Nej",
|
||||
"No File Versioning": "Ingen filversionshantering",
|
||||
"No files will be deleted as a result of this operation.": "Inga filer kommer att raderas till följd av denna operation.",
|
||||
"No files will be deleted as a result of this operation.": "Inga filer kommer att tas bort till följd av denna operation.",
|
||||
"No upgrades": "Inga uppgraderingar",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Observera",
|
||||
@@ -219,19 +222,20 @@
|
||||
"Pause": "Pausa",
|
||||
"Pause All": "Pausa alla",
|
||||
"Paused": "Pausad",
|
||||
"Paused (Unused)": "Pausad (oanvänd)",
|
||||
"Pending changes": "Väntar på ändringar",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodisk skanning i givet intervall och inaktiverad övervakning av ändringar",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodisk skanning i givet intervall och aktiverad övervakning av ändringar",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodisk skanning i givet intervall och misslyckades med att ställa in utkik efter ändringar, försök igen var 1m:",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodisk skanning vid givna intervall och misslyckades med att ställa in bevakning av ändringar, försöker igen varje 1m:",
|
||||
"Permissions": "Behörigheter",
|
||||
"Please consult the release notes before performing a major upgrade.": "Läs igenom versionsnyheterna innan den stora uppgraderingen.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Ställ in ett grafiska gränssnittets användarautentisering och lösenord i inställningsdialogrutan.",
|
||||
"Please wait": "Var god vänta",
|
||||
"Please consult the release notes before performing a major upgrade.": "Vänligen läs igenom versionsnyheterna innan du utför en större uppgradering.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Vänligen ange en användare och lösenord för gränssnittets autentisering i inställningsdialogrutan.",
|
||||
"Please wait": "Vänligen vänta",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefix som indikerar att filen kan tas bort om det förhindrar mappborttagning",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefix som indikerar att mönstret ska matchas utan skiftlägeskänslighet",
|
||||
"Preparing to Sync": "Förberedelser för synkronisering",
|
||||
"Preview": "Förhandsgranska",
|
||||
"Preview Usage Report": "Förhandsgranska statistik",
|
||||
"Preview Usage Report": "Förhandsgranska användningsrapport",
|
||||
"Quick guide to supported patterns": "Snabb handledning till mönster som stöds",
|
||||
"RAM Utilization": "RAM användning",
|
||||
"Random": "Slumpmässig",
|
||||
@@ -312,7 +316,7 @@
|
||||
"Syncthing is upgrading.": "Syncthing uppgraderas.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing stöder nu automatiskt kraschrapportering till utvecklarna. Den här funktionen är aktiverad som standard.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing verkar avstängd eller så är det problem med din Internetanslutning. Försöker igen...",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing verkar ha drabbats av ett problem med behandlingen av din begäran. Uppdatera sidan eller starta om Syncthing om problemet kvarstår.",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing verkar ha drabbats av ett problem med behandlingen av din förfrågan. Vänligen uppdatera sidan eller starta om Syncthing om problemet kvarstår.",
|
||||
"Take me back": "Ta mig tillbaka",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Det grafiska gränssnittets adressen åsidosätts av startalternativ. Ändringar här träder inte i kraft så länge åsidosättandet är på plats.",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing administratör gränssnittet är konfigurerat för att tillåta fjärrtillträde utan ett lösenord.",
|
||||
@@ -320,7 +324,7 @@
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigurationen har sparats men inte aktiverats. Syncthing måste startas om för att aktivera den nya konfigurationen.",
|
||||
"The device ID cannot be blank.": "Enhets-ID kan inte vara tomt.",
|
||||
"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).": "Enhets-ID som behövs här kan du hitta i \"Åtgärder > Visa ID\"-dialogrutan på den andra enheten. Mellanrum och bindestreck är valfria (ignoreras).",
|
||||
"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.": "Den krypterade användarstatistiken skickas dagligen. Den används för att spåra vanliga plattformar, mappstorlekar och versioner. Om datat som rapporteras ändras så kommer du att bli tillfrågad igen.",
|
||||
"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.": "Den krypterade användningsrapporten skickas dagligen. Det används för att spåra vanliga plattformar, mappstorlekar och appversioner. Om den rapporterade datauppsättningen ändras kommer du att uppmanas med den här dialogrutan igen.",
|
||||
"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.": "Det inmatade enhets-ID:t verkar inte vara korrekt. Det ska vara en 52 eller 56 teckensträng bestående av siffror och bokstäver, eventuellt med mellanrum och bindestreck.",
|
||||
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "Den första kommandoparametern är sökvägen till mappen och den andra parametern är den relativa sökvägen i mappen.",
|
||||
"The folder ID cannot be blank.": "Mapp-ID får inte vara tomt.",
|
||||
@@ -330,7 +334,7 @@
|
||||
"The following items could not be synchronized.": "Följande objekt kunde inte synkroniseras.",
|
||||
"The following items were changed locally.": "Följande objekt ändrades lokalt.",
|
||||
"The maximum age must be a number and cannot be blank.": "Åldersgränsen måste vara ett tal och kan inte lämnas tomt.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Den längsta tiden att behålla en version (i dagar, sätt till 0 för att behålla versioner för evigt).",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Den längsta tiden att behålla en version (i dagar, ställ in på 0 för att behålla versioner för alltid).",
|
||||
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "Minimum ledigt diskutrymme i procent måste vara en icke negativ siffra mellan 0 och 100 (inklusive).",
|
||||
"The number of days must be a number and cannot be blank.": "Antalet dagar måste vara en siffra och får inte vara tomt.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Antalet dagar som filer ligger kvar i papperskorgen. Noll betyder för alltid.",
|
||||
@@ -373,7 +377,7 @@
|
||||
"Version": "Version",
|
||||
"Versions": "Versioner",
|
||||
"Versions Path": "Sökväg för versioner",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versioner raderas automatiskt när de är äldre än den maximala åldersgränsen eller överstiger frekvensen i intervallet.",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versioner tas bort automatiskt när de är äldre än den maximala åldersgränsen eller överstiger frekvensen i intervallet.",
|
||||
"Waiting to Scan": "Väntar på att skanna",
|
||||
"Waiting to Sync": "Väntar på att synkronisera",
|
||||
"Waiting to scan": "Väntar på att skanna",
|
||||
@@ -382,9 +386,9 @@
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Varning, denna sökväg är en undermapp till en befintlig mapp \"{{otherFolder}}\".",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varning, denna sökväg är en undermapp av en befintlig mapp \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Varning: Om du använder en extern bevakare som {{syncthingInotify}}, bör du se till att den är inaktiverad.",
|
||||
"Watch for Changes": "Håll utkik efter ändringar",
|
||||
"Watching for Changes": "Håller utkik efter ändringar",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Hålla utkik efter ändringar upptäcker de flesta förändringar utan periodisk skanning.",
|
||||
"Watch for Changes": "Bevaka ändringar",
|
||||
"Watching for Changes": "Bevakar ändringar",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Bevakar ändringar upptäcker de flesta ändringar utan periodisk skanning.",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "När du lägger till en ny enhet, kom ihåg att den här enheten måste läggas till på den andra enheten också.",
|
||||
"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.": "När du lägger till ny mapp, tänk på att mapp-ID knyter ihop mappar mellan olika enheter. De skiftlägeskänsliga och måste matcha precis mellan alla enheter.",
|
||||
"Yes": "Ja",
|
||||
@@ -393,7 +397,7 @@
|
||||
"You can read more about the two release channels at the link below.": "Du kan läsa mer om de två publiceringsskanalerna på länken nedan.",
|
||||
"You have no ignored devices.": "Du har inga ignorerade enheter.",
|
||||
"You have no ignored folders.": "Du har inga ignorerade mappar.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "Du har ändringar som inte sparats. Vill du verkligen kassera dem?",
|
||||
"You have unsaved changes. Do you really want to discard them?": "Du har osparade ändringar. Vill du verkligen kasta dem?",
|
||||
"You must keep at least one version.": "Du måste behålla åtminstone en version.",
|
||||
"days": "dagar",
|
||||
"directories": "mappar",
|
||||
|
||||
409
gui/default/assets/lang/lang-tr.json
Normal file
409
gui/default/assets/lang/lang-tr.json
Normal file
@@ -0,0 +1,409 @@
|
||||
{
|
||||
"A device with that ID is already added.": "Bu ID'yi taşıyan aygıt zaten eklendi.",
|
||||
"A negative number of days doesn't make sense.": "Eksi gün sayısı mantıklı bir ifade değil.",
|
||||
"A new major version may not be compatible with previous versions.": "Yeni ana sürüm, önceki sürümlerle uyumlu olmayabilir.",
|
||||
"API Key": "API Anahtarı",
|
||||
"About": "Hakkında",
|
||||
"Action": "Eylem",
|
||||
"Actions": "Eylemler",
|
||||
"Add": "Ekle",
|
||||
"Add Device": "Aygıt Ekle",
|
||||
"Add Folder": "Klasör Ekle",
|
||||
"Add Remote Device": "Uzak Aygıt Ekle",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Karşılıklı paylaşılan klasörler için tanıtıcıdan aygıt listenize cihaz ekleyin.",
|
||||
"Add new folder?": "Yeni klasör ekle?",
|
||||
"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.": "Ek olarak, tam tekrar tarama aralığı artacaktır (x60, yani 1 saat yeni varsayılan). Ayrıca, hayır'ı seçtikten sonra daha sonra her klasör için elle yapılandırabilirsiniz.",
|
||||
"Address": "Adres",
|
||||
"Addresses": "Adresler",
|
||||
"Advanced": "Gelişmiş",
|
||||
"Advanced Configuration": "Gelişmiş Ayarlar",
|
||||
"Advanced settings": "Gelişmiş ayarlar",
|
||||
"All Data": "Tüm Veriler",
|
||||
"Allow Anonymous Usage Reporting?": "Anonim kullanımın raporlanmasına izin veriyor musun ?",
|
||||
"Allowed Networks": "İzinli Ağlar",
|
||||
"Alphabetic": "Alfabetik",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Harici bir komut sürüm oluşturma işlemini gerçekleştirir. Dosyayı paylaşılan klasörden kaldırmalıdır.",
|
||||
"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.": "Harici bir komut sürüm oluşturma işlemini gerçekleştirir. Dosyayı paylaşılan klasörden kaldırmalıdır. Uygulama yolu boşluk içeriyorsa, tırnak içine alınmalıdır.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Sürümleme işlemini harici bir komut yürütüyor. Dosyayı eşzamanlama klasöründen kaldırmak zorunda.",
|
||||
"Anonymous Usage Reporting": "Anonim Kullanım Raporlaması",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonim kullanım raporu formatı değişti. Yeni formata geçmek ister misiniz?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Tanıtıcı bir cihaz üzerinde yapılandırılan cihazlar bu cihaza da eklenecektir.",
|
||||
"Are you sure you want to remove device {%name%}?": " {{name}} Cihazını kaldırmak istediğine emin misin ?",
|
||||
"Are you sure you want to remove folder {%label%}?": " {{label}} Klasörünü kaldırmak istediğine emin misin ?",
|
||||
"Are you sure you want to restore {%count%} files?": "{{count}} adet dosyayı geri yüklemek istediğine emin misin ?",
|
||||
"Are you sure you want to upgrade?": "Yeni sürüme geçmek istediğinizden emin misiniz?",
|
||||
"Auto Accept": "Otomatik Kabul Et",
|
||||
"Automatic Crash Reporting": "Otomatik çökme raporu",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Otomatik güncelleme artık kararlı dağıtımlar ve sürüm adayları arasında seçim yapmayı sağlıyor.",
|
||||
"Automatic upgrades": "Otomatik güncellemeler",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Deneysel sürümler için otomatik yükseltme her zaman etkin.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Bu cihazın tanıttığı klasörleri otomatik olarak varsayılan yolda oluşturun veya paylaşın.",
|
||||
"Available debug logging facilities:": "Müsait hata ayıklama araçları",
|
||||
"Be careful!": "Dikkatli ol!",
|
||||
"Bugs": "Yazılım Hataları",
|
||||
"CPU Utilization": "İşlemci Kullanımı",
|
||||
"Changelog": "Değişim Günlüğü",
|
||||
"Clean out after": "Şundan sonra temizle",
|
||||
"Click to see discovery failures": "Keşfetme hatalarını görmek için tıklayınız",
|
||||
"Close": "Kapat",
|
||||
"Command": "Komut",
|
||||
"Comment, when used at the start of a line": "Satır başında kullanıldığında açıklama özelliği taşır",
|
||||
"Compression": "Sıkıştırma",
|
||||
"Configured": "Yapılandırıldı",
|
||||
"Connected (Unused)": "Bağlandı(Boşta)",
|
||||
"Connection Error": "Bağlantı hatası",
|
||||
"Connection Type": "Bağlantı Türü",
|
||||
"Connections": "Bağlantılar",
|
||||
"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.": "Değişiklikleri sürekli izlemek, Artık Syncthing'te kullanılabilir. Bu, diskteki değişiklikleri algılar ve yalnızca değiştirilen yollarda bir tarama yapar. Avantajları ise değişikliklerin daha hızlı yayılması ve daha az tam tarama yapılması gerektirmesidir.",
|
||||
"Copied from elsewhere": "Başka bir yerden kopyalanmış",
|
||||
"Copied from original": "Aslından kopyalanmış",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Telif Hakkı © 2014-2016 takip eden Katkıcılar:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Telif Hakkı © 2014-2017 takip eden Katkıcılar:",
|
||||
"Copyright © 2014-2019 the following Contributors:": "Her hakkı saklıdır © 2014-2019 Katkıda Bulunanlar:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Yok sayma desenleri oluşturuluyor, {{path}} klasöründeki dosyaların üzerine yazılıyor",
|
||||
"Currently Shared With Devices": "Cihazlarla Paylaşılanlar",
|
||||
"Danger!": "Tehlike!",
|
||||
"Debugging Facilities": "Hata Ayıklama Araçları",
|
||||
"Default Folder Path": "Varsayılan Klasör Yolu",
|
||||
"Deleted": "Silindi",
|
||||
"Deselect All": "Tüm Seçimi Kaldır",
|
||||
"Deselect devices to stop sharing this folder with.": "Bu klasörün paylaşılmasını istemediğiniz cihazların seçimini kaldırın",
|
||||
"Device": "Cihaz",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "\"{{name}}\" aygıtı ({{address}} adresindeki {{device}}) bağlanmak istiyor. Yeni aygıtı ekliyor musun?",
|
||||
"Device ID": "Cihaz ID",
|
||||
"Device Identification": "Cihaz Kimliği",
|
||||
"Device Name": "Cihaz Adı",
|
||||
"Device rate limits": "Cihaz Bağlantı Limitleri",
|
||||
"Device that last modified the item": "Öğeyi son değiştiren cihaz",
|
||||
"Devices": "Cihazlar",
|
||||
"Disable Crash Reporting": "Çökme Raporlarını Devreden Çıkar",
|
||||
"Disabled": "Aktif Değil",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Periyodik taramayı ve değişiklikleri izlemeyi devreden çıkar",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Periyodik taramayı devreden çıkar ve değişiklikleri izlemeyi etkinleştir",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Periyodik tarama devredışı, değişiklikler için tarama devreye alınamadı, tekrar deneme süresi 1 dakika:",
|
||||
"Discard": "Yoksay",
|
||||
"Disconnected": "Bağlantı Kesik",
|
||||
"Disconnected (Unused)": "Bağlantı Kesildi(Boşta)",
|
||||
"Discovered": "Keşfedildi",
|
||||
"Discovery": "Keşif",
|
||||
"Discovery Failures": "Keşfetme Hataları",
|
||||
"Do not restore": "Geri yükleme",
|
||||
"Do not restore all": "Hiçbirini geri yükleme",
|
||||
"Do you want to enable watching for changes for all your folders?": "Tüm klasörleriniz için değişiklikleri izlemeyi etkinleştirmek ister misiniz?",
|
||||
"Documentation": "Belgeleme",
|
||||
"Download Rate": "İndirme Hızı",
|
||||
"Downloaded": "İndirilmiş",
|
||||
"Downloading": "İndiriliyor",
|
||||
"Edit": "Düzenle",
|
||||
"Edit Device": "Aygıtı Düzenle",
|
||||
"Edit Folder": "Klasörü Düzenle",
|
||||
"Editing": "Düzenleniyor",
|
||||
"Editing {%path%}.": "{{path}} Düzenleniyor.",
|
||||
"Enable Crash Reporting": "Çökme Raporlarını etkinleştrir",
|
||||
"Enable NAT traversal": "NAT geçişini etkinleştir",
|
||||
"Enable Relaying": "Aktarmayı Etkinleştir",
|
||||
"Enabled": "Aktif",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Eksi olmayan bir sayı giriniz (örneğin, \"2.35\") ve bir ünite seçiniz. Bu toplam diskte kullanılacak yüzdeyi gösterir",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Yetki gerektirmeyen bir port numarası giriniz (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Adreslerin kendiliğinden keşfedilebilmesi için ya adresleri virgülle ayırarak (\"tcp://ip:port\", \"tcp://host:port\") girin, ya da \"dynamic\" sözcüğünü girin.",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Adresleri virgülle ayırarak (\"tcp://ip:port\", \"tcp://host:port\") veya otomatik adres bulma için \"dynamic\" yazarak giriş yapınız",
|
||||
"Enter ignore patterns, one per line.": "Gözardı edilmesini istediğiniz kalıp dizilerini her satıra bir tane olacak şekilde girin.",
|
||||
"Enter up to three octal digits.": "Üç haneye kadar sekizlik sayı girin.",
|
||||
"Error": "Hata",
|
||||
"External File Versioning": "Harici Dosya Sürümleme İşlemi",
|
||||
"Failed Items": "Başarısız Olunan Ögeler",
|
||||
"Failed to load ignore patterns": "Yoksayma desenleri yükleme hatası",
|
||||
"Failed to setup, retrying": "Kurulum başarısız, tekrar deneniyor",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "IPv6 bağlantısı yoksa IPv6 sunucularına bağlanılamaması beklenir.",
|
||||
"File Pull Order": "Dosya Çekme Sırası",
|
||||
"File Versioning": "Dosya Sürümleme İşlemi",
|
||||
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Değişimleri tararken dosya izin bilgilerini gözardı et. FAT dosya sistemlerinde kullanılır.",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Dosyalar silindiğinde veya değiştirildiğinde Syncthing tarafından .stversions klasörüne taşınır.",
|
||||
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Dosyalar Syncthing tarafından yeri değiştirildiğinde ya da silindiğinde .stversions klasörüne taşınır.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Dosyalar değiştirildiğinde veya silindiğinde, Syncthing tarafından tarih damgalı versiyonları .stversions klasörüne taşınır.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Dosyalar Syncthing tarafından yeri değiştirildiğinde ya da silindiğinde, tarih damgalı sürümleri .stversions klasörüne taşınır.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Dosyalar diğer aygıtlarda yapılan değişikliklerden korunur, ancak bu aygıttaki değişiklikler kümedeki diğer aygıtlara gönderilir.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Dosyalar kümeden senkronize edilmektedir, bu sebeple yerel olarak yapılan değişiklikler diğer cihazlara gönderilmez.",
|
||||
"Filesystem Notifications": "Dosya Sistemi Bildirimleri",
|
||||
"Filesystem Watcher Errors": "Dosya Sistemi İzleyici Hataları",
|
||||
"Filter by date": "Tarihe göre filtrele",
|
||||
"Filter by name": "İsme göre filtrele",
|
||||
"Folder": "Klasör",
|
||||
"Folder ID": "Klasör ID",
|
||||
"Folder Label": "Klasör Etiketi",
|
||||
"Folder Path": "Klasör Yolu",
|
||||
"Folder Type": "Klasör Türü",
|
||||
"Folders": "Klasörler",
|
||||
"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.": "Aşağıdaki klasörler için değişiklikleri izlemeye başlarken bir hata oluştu. Her dakika yeniden denenecek, böylece hatalar kısa süre içinde ortadan kalkacaktır. Devam ederse, altta yatan sorunu düzeltmeyi deneyin ve yapamıyorsanız yardım isteyin.",
|
||||
"Full Rescan Interval (s)": "Tam Tekrar Tarama Aralığı (s)",
|
||||
"GUI": "GUI / Grafiksel Kullanıcı Arayüzü",
|
||||
"GUI Authentication Password": "GUI Kimlik Doğrulaması için Kullanıcı Parolası",
|
||||
"GUI Authentication User": "GUI Kimlik Doğrulaması için Kullanıcı Adı",
|
||||
"GUI Listen Address": "GUI Bağlantı Adresi",
|
||||
"GUI Listen Addresses": "GUI Dinleme/Bağlantı Adresleri",
|
||||
"GUI Theme": "GUI Teması",
|
||||
"General": "Genel",
|
||||
"Generate": "Oluştur",
|
||||
"Global Changes": "Global Değişiklikler",
|
||||
"Global Discovery": "Küresel Discovery",
|
||||
"Global Discovery Servers": "Global Keşif Sunucuları",
|
||||
"Global State": "Global Durum",
|
||||
"Help": "Yardım",
|
||||
"Home page": "Ana sayfa",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Ancak, mevcut ayarlarınız etkinleştirilmesini istemediğinizi gösterir. Sizin için otomatik çökme raporlamasını devre dışı bıraktık.",
|
||||
"Ignore": "Yoksay",
|
||||
"Ignore Patterns": "Yoksayılan Kalıp Dizileri",
|
||||
"Ignore Permissions": "İzinleri Yoksay",
|
||||
"Ignored Devices": "Yoksayılan Cihazlar",
|
||||
"Ignored Folders": "Yoksayılan Dizinler",
|
||||
"Ignored at": "Yoksay",
|
||||
"Incoming Rate Limit (KiB/s)": "İndirme Limiti (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Yanlış yapılandırma klasör içeriğine zarar verebilir ve Syncthing'i çalışamaz hale getirebilir.",
|
||||
"Introduced By": "Tanıtan",
|
||||
"Introducer": "Tanıtıcı",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Verilen koşulun ters çevirilmesi (örneğin: yok sayma)",
|
||||
"Keep Versions": "Sürümleri Tut",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "En büyük olan önce",
|
||||
"Last File Received": "Alınan Son Dosya",
|
||||
"Last Scan": "Son Tarama",
|
||||
"Last seen": "Son görülme",
|
||||
"Later": "Sonra",
|
||||
"Latest Change": "Son Değişim",
|
||||
"Learn more": "Daha çoğunu öğren",
|
||||
"Limit": "Limit",
|
||||
"Listeners": "Dinleyiciler",
|
||||
"Loading data...": "Veri yükleniyor...",
|
||||
"Loading...": "Yükleniyor...",
|
||||
"Local Additions": "Yerel İlaveler",
|
||||
"Local Discovery": "Yerel Discovery",
|
||||
"Local State": "Yerel Durum",
|
||||
"Local State (Total)": "Yerel Durum (Toplamı)",
|
||||
"Locally Changed Items": "Yerel Olarak Değiştirilen Öğeler",
|
||||
"Log": "Günlük",
|
||||
"Log tailing paused. Click here to continue.": "Günlük kuyruğu duraklatıldı. Devam etmek için buraya tıklayın.",
|
||||
"Log tailing paused. Scroll to bottom continue.": "Günlük kuyruğu duraklatıldı. Devam etmek için aşağı kaydırın.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Günlük kuyruğu duraklatıldı. Devam etmek için aşağı kaydırın.",
|
||||
"Logs": "Günlükler",
|
||||
"Major Upgrade": "Birincil Yükseltme",
|
||||
"Mass actions": "Toplu İşlemler",
|
||||
"Master": "Ana",
|
||||
"Maximum Age": "Azami Süre",
|
||||
"Metadata Only": "Yalnızca Üstveri",
|
||||
"Minimum Free Disk Space": "En Az Boş Disk Alanı",
|
||||
"Mod. Device": "Değiştiren Cihaz",
|
||||
"Mod. Time": "Değiştirilme Zamanı",
|
||||
"Move to top of queue": "Kuyruğun başına taşı",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Çoklu düzey wildcard (çok sayıda dizin düzeyinde eşleşme)",
|
||||
"Never": "Asla",
|
||||
"New Device": "Yeni Aygıt",
|
||||
"New Folder": "Yeni Klasör",
|
||||
"Newest First": "En yeni olan önce",
|
||||
"No": "Hayır",
|
||||
"No File Versioning": "Dosya Sürümleme İşlemi Yok",
|
||||
"No files will be deleted as a result of this operation.": "Bu işlem sonucunda hiçbir dosya silinmeyecek.",
|
||||
"No upgrades": "Yükseltme yok",
|
||||
"Normal": "Olağan",
|
||||
"Notice": "Uyarı",
|
||||
"OK": "Tamam",
|
||||
"Off": "Kapalı",
|
||||
"Oldest First": "En eski olan önce",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Klasör için isteğe bağlı açıklayıcı etiket. Her aygıtta başka olabilir.",
|
||||
"Options": "Seçenekler",
|
||||
"Out of Sync": "Eşzamanlama Dışı",
|
||||
"Out of Sync Items": "Senkronizasyon Dışında Kalan Ögeler",
|
||||
"Outgoing Rate Limit (KiB/s)": "Yükleme hız sınırı (KB/sn)",
|
||||
"Override Changes": "Değişiklikleri Geçersiz kıl",
|
||||
"Path": "Yol",
|
||||
"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": "Yerel bilgisayardaki klasöre ulaşım yolu. Klasör yoksa yaratılacak. Tilde (~) karakterinin kısayol olarak kullanılabileceği yol",
|
||||
"Path where new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {%tilde%}.": "Yeni otomatik kabul edilen klasörlerin oluşturulacağı yolun yanı sıra kullanıcı arayüzü aracılığıyla yeni klasörler eklerken varsayılan önerilen yol. Tilde karakteri (~) {{tilde}} 'a genişler.",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Sürümlerin depolanması gereken yol (paylaşılan klasördeki varsayılan .stversions dizini için boş bırakın).",
|
||||
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Sürümlerin saklanması için gereken klasör yolu (öntanımlı .stversions klasörü için boş bırakın)",
|
||||
"Pause": "Duraklat",
|
||||
"Pause All": "Tümünü Duraklat",
|
||||
"Paused": "Duraklatıldı",
|
||||
"Paused (Unused)": "Durdu(Boşta)",
|
||||
"Pending changes": "Bekleyen değişiklikler",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Belirli aralıklarla periyodik tarama ve değişiklikleri izlemeyi devre dışı bırakma",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Belirli aralıklarla periyodik tarama ve değişiklikleri izleme olanağı",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Belirli aralıklarla periyodik tarama ve değişiklikleri izleme başarısız, her 1 dakikada tekrar deneniyor:",
|
||||
"Permissions": "Yetkiler",
|
||||
"Please consult the release notes before performing a major upgrade.": "Birincil bir yükseltme gerçekleştirmeden önce lütfen sürüm notlarını tetkik edin.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "GUI üzerinden Kimlik Doğrulaması yapmak için Ayarlar penceresinde Kullanıcı ve Parola tanımlayın lütfen.",
|
||||
"Please wait": "Lütfen Bekleyin",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Dizin kaldırılmasını önlüyorsa dosyanın silinebileceğini gösteren önek",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Desenin büyük / küçük harf duyarlılığı olmadan eşleştirilmesi gerektiğini gösteren önek",
|
||||
"Preparing to Sync": "Senkronizasyon için Hazırlanıyor",
|
||||
"Preview": "Önizleme",
|
||||
"Preview Usage Report": "Kullanım raporunu gözden geçir",
|
||||
"Quick guide to supported patterns": "Desteklenen kalıp dizileri için hızlı rehber",
|
||||
"RAM Utilization": "RAM Kullanımı",
|
||||
"Random": "Rastgele",
|
||||
"Receive Only": "Sadece Al",
|
||||
"Recent Changes": "Son Değişiklikler",
|
||||
"Reduced by ignore patterns": "Gözardı edilen kalıp dizileri tarafından daraltıldı",
|
||||
"Release Notes": "Sürüm Notları",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Sürüm adayları en son özellikleri ve hata düzeltmelerini içerir. Bunlar, geleneksel olarak iki haftada bir yayımlanan Syncthing dağıtımlarına benzer.",
|
||||
"Remote Devices": "Uzak Aygıtlar",
|
||||
"Remove": "Kaldır",
|
||||
"Remove Device": "Aygıtı Kaldır",
|
||||
"Remove Folder": "Dizini Kaldır",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Klasör için tanımlayıcı gereklidir. Tüm küme cihazlarda aynı olmalıdır.",
|
||||
"Rescan": "Tekrar Tara",
|
||||
"Rescan All": "Tümünü Tekrar Tara",
|
||||
"Rescan Interval": "Tarama Aralığı",
|
||||
"Rescans": "Yeniden Tara",
|
||||
"Restart": "Yeniden Başlat",
|
||||
"Restart Needed": "Yeniden başlatma gereklidir",
|
||||
"Restarting": "Yeniden başlatılıyor",
|
||||
"Restore": "Geri Yükle",
|
||||
"Restore Versions": "Geri Yükleme Versiyonları",
|
||||
"Resume": "Devam Et/Sürdür",
|
||||
"Resume All": "Tümünü Devam Ettir",
|
||||
"Reused": "Yeniden Kullanılan",
|
||||
"Revert Local Changes": "Yerel Değişiklikleri Geri Döndür",
|
||||
"Running": "Çalışıyor",
|
||||
"Save": "Kaydet",
|
||||
"Scan Time Remaining": "Kalan Tarama Zamanı",
|
||||
"Scanning": "Taranıyor",
|
||||
"See external versioner help for supported templated command line parameters.": "Desteklenen şablonlanmış komut satırı parametreleri için harici sürüm oluşturucu yardımına bakın.",
|
||||
"See external versioning help for supported templated command line parameters.": "Desteklenen şablonlanmış komut satırı parametreleri için harici sürüm oluşturma yardımına bakın.",
|
||||
"Select All": "Tümünü Seç",
|
||||
"Select a version": "Bir sürüm seçin",
|
||||
"Select additional devices to share this folder with.": "Bu klasörün paylaşılacağı ilave cihazları seçiniz",
|
||||
"Select latest version": "En yeni sürümü seç",
|
||||
"Select oldest version": "En eski sürümü seç",
|
||||
"Select the devices to share this folder with.": "Bu klasörü paylaşacağın aygıtları seç.",
|
||||
"Select the folders to share with this device.": "Bu aygıtla paylaşılacak klasörleri seç.",
|
||||
"Send & Receive": "Gönder & Al",
|
||||
"Send Only": "Yalnızca Gönder",
|
||||
"Settings": "Ayarlar",
|
||||
"Share": "Paylaş",
|
||||
"Share Folder": "Paylaşım Klasörü",
|
||||
"Share Folders With Device": "Klasörleri Aygıtla Paylaş",
|
||||
"Share With Devices": "Aygıtlar İle Paylaş",
|
||||
"Share this folder?": "Bu klasörü paylaş?",
|
||||
"Shared With": "Paylaşılan düğümler",
|
||||
"Sharing": "Paylaşılıyor",
|
||||
"Show ID": "ID Göster",
|
||||
"Show QR": "QR 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 Aygıt ID yerine bunu göster. Varsayılan ad isteğe bağlı olarak diğer aygıtlara ilan edilecektir.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Küme durumunda Aygıt ID yerine bunu göster. Eğer düğüm adı boş bırakılırsa düğüm adı güncellenip ilan edilecektir.",
|
||||
"Shutdown": "Kapat",
|
||||
"Shutdown Complete": "Kapatma İşlemi Tamamlandı",
|
||||
"Simple File Versioning": "Basit Dosya Sürümleme İşlemi",
|
||||
"Single level wildcard (matches within a directory only)": "Tekli düzey wildcard (yalnızca bir dizin içinde eşleşme)",
|
||||
"Size": "Boyut",
|
||||
"Smallest First": "En küçük olan önce",
|
||||
"Some items could not be restored:": "Bazı öğeler geri yüklenemedi",
|
||||
"Source Code": "Kaynak Kodu",
|
||||
"Stable releases and release candidates": "Kararlı dağıtımlar ve sürüm adayları",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Kararlı dağıtımlar aşağı yukarı iki hafta gecikir. Bu zaman zarfında sürüm adayı olarak sınanırlar.",
|
||||
"Stable releases only": "Yalnızca kararlı dağıtımlar",
|
||||
"Staggered File Versioning": "Aşamalı Dosya Sürümleme İşlemi",
|
||||
"Start Browser": "Tarayıcıyı Başlat",
|
||||
"Statistics": "İstatistikler",
|
||||
"Stopped": "Durduruldu",
|
||||
"Support": "Destek",
|
||||
"Support Bundle": "Destek Paketi",
|
||||
"Sync Protocol Listen Addresses": "Sync Protokol Dinleme Adresleri",
|
||||
"Syncing": "Eşzamanlama gerçekleştiriliyor",
|
||||
"Syncthing has been shut down.": "Syncthing kapatıldı",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing aşağıdaki yazılımları veya bunların bölümlerini içermektedir:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing, MPL v2.0 ile lisanslanan Özgür ve Açık Kaynak bir yazılımdır.",
|
||||
"Syncthing is restarting.": "Syncthing yeniden başlatılıyor.",
|
||||
"Syncthing is upgrading.": "Syncthing yükseltiliyor.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing artık çökmeleri geliştiricilere otomatik olarak raporlamayı destekliyor. Bu özellik ön tanımlı olarak etkinleştirilmiştir.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing uygulaması çökmüş olabilir, veya internet bağlantınızda bir sorun var. Tekrar deniyor....",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing isteminizi işleme alırken bir sorunla karşılaştı. Lütfen sayfanızı yenileyin veya sorun devam ediyorsa Syncthing'i yeniden başlatın.",
|
||||
"Take me back": "Geriye Git",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "GUI adresi, başlangıç ayarları ile geçersiz kılınmıştır. Bu durum devam ettikçe, burada yapılacak değişiklikler etki göstermeyecektir.",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing yönetici arayüzü parolasız olarak uzaktan erişime izin verilecek şekilde yapılandırıldı.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Toplanan istatistikler halka açık biçimde aşağıdaki adrestedir.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Yapılandırma kaydedildi ancak etkinleştirilmedi. Etkinleştirmek için Syncthing yeniden başlatılmalı.",
|
||||
"The device ID cannot be blank.": "Aygıt ID değeri boş bırakılamaz.",
|
||||
"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).": "Buraya girilecek olan aygıt ID'si diğer aygıtlarda \"Eylemler > ID Göster\" penceresinde bulunabilir. Boşluklar ve çizgiler isteğe bağlıdır (gözardı edilmiş).",
|
||||
"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.": "Şifrelenmiş kullanım bilgisi günlük olarak gönderilir. Platform, klasör büyüklüğü ve uygulama sürümü hakkında bilgi toplanır. Toplanan bilgi türü değişecek olursa, sizden yeniden onay istenecek.",
|
||||
"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.": "Girilen aygıt ID'si geçerli gibi gözükmüyor. 52 ya da 56 karakter uzunluğunda, harf ve rakamlardan oluşmalı. Boşlukların ve kısa çizgilerin olup olmaması önemli değildir.",
|
||||
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "İlk komut satırı parametresi klasör yoludur; ikinci parametre ise klasördeki göreceli yoldur. ",
|
||||
"The folder ID cannot be blank.": "Klasör ID değeri boş bırakılamaz",
|
||||
"The folder ID must be unique.": "Klasör ID benzersiz olmalıdır.",
|
||||
"The folder path cannot be blank.": "Klasör yolu boş bırakılamaz.",
|
||||
"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.": "Kullanılan zaman aralıkları: ilk bir saat zarfında her 30 saniyede bir, ilk gün zarfında saatte bir, ilk 30 gün zarfında her gün, azami süreye kadar geçen zamanda ise her hafta yeni bir sürüm değeri oluşturulur/tutulur.",
|
||||
"The following items could not be synchronized.": "Aşağıdaki ögelerin eşzamanlama işlemi gerçekleştirilemedi.",
|
||||
"The following items were changed locally.": "Aşağıdaki öğeler yerel olarak değiştirildi.",
|
||||
"The maximum age must be a number and cannot be blank.": "Azami süre tanımı boş bırakılmamalı ve bir sayı olarak tanımlanmalıdır.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Bir sürümün tutulması için belirlenen azami süre (sürümleri sürekli olarak tutabilmek için 0 değeri atayın)",
|
||||
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "En küçük boş disk alanı yüzde olarak 0 ve 100 (dahil) arasında kalan pozitif bir sayıyla tanımlanmalıdır.",
|
||||
"The number of days must be a number and cannot be blank.": "Gün sayısı boş bırakılmamalı ve bir sayı olarak tanımlanmalıdır.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Dosyaları çöp kutusunda tutma süresini tanımlayan gün sayısı. Sıfır devamlı/sürekli anlamına gelir.",
|
||||
"The number of old versions to keep, per file.": "Dosya başına saklanacak/tutulacak eski sürüm sayısı.",
|
||||
"The number of versions must be a number and cannot be blank.": "Sürümlerin sayısı boş bırakılamamalı ve bir sayı olarak tanımlanmalıdır.",
|
||||
"The path cannot be blank.": "Yol tanımı boş bırakılamaz.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Hız sınırı pozitif bir sayı olmalıdır. (0: sınırsız)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Tarama zaman aralığı, saniye cinsinden negatif olmayan bir sayı olmalıdır.",
|
||||
"There are no devices to share this folder with.": "Bu klasörü paylaşacak cihaz yok",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "Kendiliğinden yeniden deneniyor; hata giderildiğinde eşzamanlama gerçekleştirilecek.",
|
||||
"This Device": "Bu Aygıt",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Hacker'ların bilgisayarındaki dosyaları okuma ve değiştirme yetkisine kolayca erişmelerini sağlayabilir.",
|
||||
"This is a major version upgrade.": "Ana sürüm yükseltmesidir.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Bu ayar, ev diski(indeks veritabanı vb.) için gerekli boş alanı kontrol eder.",
|
||||
"Time": "Zaman",
|
||||
"Time the item was last modified": "Öğenin son düzenlendiği zaman",
|
||||
"Trash Can File Versioning": "Çöp Kutusu Dosya Sürümleme İşlemi",
|
||||
"Type": "Tür",
|
||||
"UNIX Permissions": "Unix İzinleri",
|
||||
"Unavailable": "Kullanım dışı",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Bakımcı veya yönetici tarafından devre dışı/kullanım dışı bırakıldı",
|
||||
"Undecided (will prompt)": "Karar verilmemiş (sorulacak)",
|
||||
"Unignore": "Yoksayılanlardan Çıkar",
|
||||
"Unknown": "Bilinmiyor",
|
||||
"Unshared": "Paylaşılmayan",
|
||||
"Unshared Devices": "Paylaşılmayan Cihazlar",
|
||||
"Unused": "Kullanılmayan",
|
||||
"Up to Date": "Güncel",
|
||||
"Updated": "Güncellendi",
|
||||
"Upgrade": "Sürüm Yükseltme",
|
||||
"Upgrade To {%version%}": "{{version}} sürümüne yükselt",
|
||||
"Upgrading": "Yükseltiliyor",
|
||||
"Upload Rate": "Yükleme hızı",
|
||||
"Uptime": "Çalışma Zamanı",
|
||||
"Usage reporting is always enabled for candidate releases.": "Kullanım raporu sürüm adayları için her zaman etkindir.",
|
||||
"Use HTTPS for GUI": "GUI için HTTPS kullan",
|
||||
"Use notifications from the filesystem to detect changed items.": "Değişen öğeleri tespit etmek için dosya sistemi bildirimleri kullanın.",
|
||||
"Variable Size Blocks": "Değişken Boyutlu Bloklar",
|
||||
"Variable size blocks (also \"large blocks\") are more efficient for large files.": "Değişken boyutlu bloklar (ayrıca \"büyük bloklar\") büyük dosyalar için daha verimlidir.",
|
||||
"Version": "Sürüm",
|
||||
"Versions": "Sürümler",
|
||||
"Versions Path": "Sürümler için Klasör Yolu",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Sürümler, tanımlı azami süre veya belirlenen zaman aralığı için izin verilen dosya sayısı aşılmışsa kendiliğinden silinir.",
|
||||
"Waiting to Scan": "Tarama için Bekliyor",
|
||||
"Waiting to Sync": "Senkronizasyon için Bekliyor",
|
||||
"Waiting to scan": "Tarama için bekleniyor",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Uyarı ! Bu yol varolan \"{{otherFolder}}\" klasörünün üst dizinidir.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Uyarı ! Bu yol varolan \"{{otherFolderLabel}}\" ({{otherFolder}}) klasörünün üst dizinidir.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Uyarı ! Bu yol varolan \"{{otherFolder}}\" klasörünün alt dizinidir.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Uyarı ! Bu yol var olan \"{{otherFolderLabel}}\" ({{otherFolder}}) klasörünün alt dizinidir.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Uyarı: {{syncthingInotify}} gibi bir harici izleyici kullanıyorsanız, devre dışı olduğundan emin olmalısınız.",
|
||||
"Watch for Changes": "Değişiklikleri İzle",
|
||||
"Watching for Changes": "Değişiklikler İzleniyor",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Değişiklikleri izlemek, periyodik tarama yapmadan çoğu değişikliği keşfeder.",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "Yeni bir aygıt eklendiğinde, bu aygıtın karşı tarafa da eklenmesi gerektiğini unutmayın.",
|
||||
"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.": "Yeni bir klasör eklendiğinde, Klasör ID'nin klasörleri aygıtlar arasında bağlantılandırmak için kullanıldığını unutmayın. Klasör ID'ler büyük - küçük harf duyarlıdır ve tüm aygıtlarda tamı tamına eşleşmelidir.",
|
||||
"Yes": "Evet",
|
||||
"You can also select one of these nearby devices:": "Ayrıca yakındaki cihazlardan birini de seçebilirsiniz:",
|
||||
"You can change your choice at any time in the Settings dialog.": "Seçiminizi herhangi bir zamanda Ayarlar penceresinde değiştirebilirsiniz.",
|
||||
"You can read more about the two release channels at the link below.": "İki dağıtım kanalıyla ilgili daha çoğunu aşağıdaki bağlantıdan okuyabilirsiniz.",
|
||||
"You have no ignored devices.": "Gözardı edilen cihaz yok.",
|
||||
"You have no ignored folders.": "Gözardı edilen klasör yok.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "Kayıt edilmemiş değişiklikler var. Yok saymak istediğinize eminmisiniz ?",
|
||||
"You must keep at least one version.": "En az bir sürümü tutmalısınız.",
|
||||
"days": "gün",
|
||||
"directories": "dizinler",
|
||||
"files": "dosyalar",
|
||||
"full documentation": "belgelendirme içeriğinin tümü",
|
||||
"items": "öğeler",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} \"{{folder}}\" klasörünü paylaşmak istiyor.",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} \"{{folderlabel}}\" ({{folder}}) klasörünü paylaşmak istiyor."
|
||||
}
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "Коментар, якщо використовується на початку рядка",
|
||||
"Compression": "Стиснення",
|
||||
"Configured": "Налаштовано",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "Помилка з’єднання",
|
||||
"Connection Type": "Тип з*єднання",
|
||||
"Connections": "З'єднання",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Відключено періодичне сканування та не вдається налаштувати перегляд змін, повторення кожну 1 хв:",
|
||||
"Discard": "Відхилити",
|
||||
"Disconnected": "З’єднання відсутнє",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Виявлено",
|
||||
"Discovery": "Сервери координації NAT",
|
||||
"Discovery Failures": "Помилки виявлення",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "Рекомендувач",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Інверсія поточної умови (тобто не виключає)",
|
||||
"Keep Versions": "Зберігати версії",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Спершу найбільші",
|
||||
"Last File Received": "Останній завантажений файл",
|
||||
"Last Scan": "Останнє сканування",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "Пауза",
|
||||
"Pause All": "Призупинити все",
|
||||
"Paused": "Призупинено",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "Запит на зміни поставлено в чергу",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodic scanning at given interval and disabled watching for changes",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodic scanning at given interval and enabled watching for changes",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "注释,在行首使用",
|
||||
"Compression": "压缩",
|
||||
"Configured": "已配置",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "连接出错",
|
||||
"Connection Type": "连接类型",
|
||||
"Connections": "连接",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "已禁用定期扫描但设置更改监视失败,正在以每 1m 一次重试:",
|
||||
"Discard": "丢弃",
|
||||
"Disconnected": "连接已断开",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "已发现",
|
||||
"Discovery": "设备发现",
|
||||
"Discovery Failures": "设备发现错误",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "作为中介",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "对本条件取反(例如:不要排除某项)",
|
||||
"Keep Versions": "保留版本数量",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "大文件优先",
|
||||
"Last File Received": "最后接收的文件",
|
||||
"Last Scan": "最后扫描",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "暂停",
|
||||
"Pause All": "全部暂停",
|
||||
"Paused": "已暂停",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "待定的更改",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "正以给定的间隔定期扫描并已禁用更改监视",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "正以给定的间隔定期扫描并已启用更改监视",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"Comment, when used at the start of a line": "註解,當輸入在一行的開頭時",
|
||||
"Compression": "壓縮",
|
||||
"Configured": "已設定",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Connection Error": "連線錯誤",
|
||||
"Connection Type": "連線類型",
|
||||
"Connections": "連線",
|
||||
@@ -82,6 +83,7 @@
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "已停用定期掃描,無法設定觀察變動,每 1 分鐘重試:",
|
||||
"Discard": "忽略",
|
||||
"Disconnected": "斷線",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "已發現",
|
||||
"Discovery": "探索",
|
||||
"Discovery Failures": "探索失敗",
|
||||
@@ -161,6 +163,7 @@
|
||||
"Introducer": "引入者",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "反轉給定條件 (即:不要排除)",
|
||||
"Keep Versions": "保留歷史版本數",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "最大的優先",
|
||||
"Last File Received": "最後接收的檔案",
|
||||
"Last Scan": "最後掃描",
|
||||
@@ -219,6 +222,7 @@
|
||||
"Pause": "暫停",
|
||||
"Pause All": "全部暫停",
|
||||
"Paused": "暫停",
|
||||
"Paused (Unused)": "Paused (Unused)",
|
||||
"Pending changes": "等待中的變動",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "在一定的時間間隔,定期掃描及關閉觀察變動",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "在一定的時間間隔,定期掃描及啟用觀察變動",
|
||||
|
||||
@@ -1 +1 @@
|
||||
var langPrettyprint = {"bg":"Bulgarian","ca@valencia":"Catalan (Valencian)","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","eo":"Esperanto","es":"Spanish","es-ES":"Spanish (Spain)","fi":"Finnish","fr":"French","fy":"Western Frisian","hu":"Hungarian","it":"Italian","ja":"Japanese","ko-KR":"Korean (Korea)","lt":"Lithuanian","nb":"Norwegian Bokmål","nl":"Dutch","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ru":"Russian","sk":"Slovak","sv":"Swedish","uk":"Ukrainian","zh-CN":"Chinese (China)","zh-TW":"Chinese (Taiwan)"}
|
||||
var langPrettyprint = {"bg":"Bulgarian","ca@valencia":"Catalan (Valencian)","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","eo":"Esperanto","es":"Spanish","es-ES":"Spanish (Spain)","eu":"Basque","fi":"Finnish","fr":"French","fy":"Western Frisian","hu":"Hungarian","it":"Italian","ja":"Japanese","ko-KR":"Korean (Korea)","lt":"Lithuanian","nb":"Norwegian Bokmål","nl":"Dutch","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ru":"Russian","sk":"Slovak","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","zh-CN":"Chinese (China)","zh-TW":"Chinese (Taiwan)"}
|
||||
|
||||
@@ -1 +1 @@
|
||||
var validLangs = ["bg","ca@valencia","cs","da","de","el","en","en-GB","eo","es","es-ES","fi","fr","fy","hu","it","ja","ko-KR","lt","nb","nl","pl","pt-BR","pt-PT","ru","sk","sv","uk","zh-CN","zh-TW"]
|
||||
var validLangs = ["bg","ca@valencia","cs","da","de","el","en","en-GB","eo","es","es-ES","eu","fi","fr","fy","hu","it","ja","ko-KR","lt","nb","nl","pl","pt-BR","pt-PT","ru","sk","sv","tr","uk","zh-CN","zh-TW"]
|
||||
|
||||
@@ -405,7 +405,7 @@
|
||||
<tr ng-if="folder.type == 'receiveonly' && canRevert(folder.id)">
|
||||
<th><span class="fas fa-fw fa-exclamation-circle"></span> <span translate>Locally Changed Items</span></th>
|
||||
<td class="text-right">
|
||||
<a href="" ng-click="showLocalChanged(folder.id)">{{model[folder.id].receiveOnlyTotalItems | alwaysNumber | localeNumber}} <span translate>items</span>, ~{{model[folder.id].receiveOnlyBytes | binary}}B</a>
|
||||
<a href="" ng-click="showLocalChanged(folder.id)">{{model[folder.id].receiveOnlyTotalItems | alwaysNumber | localeNumber}} <span translate>items</span>, ~{{model[folder.id].receiveOnlyChangedBytes | binary}}B</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="folder.type != 'sendreceive'">
|
||||
@@ -515,7 +515,7 @@
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="restoreVersions.show(folder.id)" ng-if="folder.versioning.type">
|
||||
<span class="fas fa-undo"></span> <span translate>Versions</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="rescanFolder(folder.id)" ng-disabled="['idle', 'stopped', 'unshared', 'outofsync', 'faileditems'].indexOf(folderStatus(folder)) < 0">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="rescanFolder(folder.id)" ng-disabled="['idle', 'stopped', 'unshared', 'outofsync', 'faileditems', 'localadditions'].indexOf(folderStatus(folder)) < 0">
|
||||
<span class="fas fa-refresh"></span> <span translate>Rescan</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="editFolder(folder)">
|
||||
@@ -656,12 +656,14 @@
|
||||
<identicon class="panel-icon" data-value="deviceCfg.deviceID"></identicon>
|
||||
<span ng-switch="deviceStatus(deviceCfg)" class="pull-right text-{{deviceClass(deviceCfg)}}">
|
||||
<span ng-switch-when="insync"><span class="hidden-xs" translate>Up to Date</span><span class="visible-xs" aria-label="{{'Up to Date' | translate}}"><i class="fas fa-fw fa-check"></i></span></span>
|
||||
<span ng-switch-when="unused-insync"><span class="hidden-xs" translate>Connected (Unused)</span><span class="visible-xs" aria-label="{{'Connected (Unused)' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
<span ng-switch-when="syncing">
|
||||
<span class="hidden-xs" translate>Syncing</span> ({{completion[deviceCfg.deviceID]._total | percent}}, {{completion[deviceCfg.deviceID]._needBytes | binary}}B)
|
||||
</span>
|
||||
<span ng-switch-when="paused"><span class="hidden-xs" translate>Paused</span><span class="visible-xs" aria-label="{{'Paused' | translate}}"><i class="fas fa-fw fa-pause"></i></span></span>
|
||||
<span ng-switch-when="unused-paused"><span class="hidden-xs" translate>Paused (Unused)</span><span class="visible-xs" aria-label="{{'Paused (Unused)' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
<span ng-switch-when="disconnected"><span class="hidden-xs" translate>Disconnected</span><span class="visible-xs" aria-label="{{'Disconnected' | translate}}"><i class="fas fa-fw fa-power-off"></i></span></span>
|
||||
<span ng-switch-when="unused"><span class="hidden-xs" translate>Unused</span><span class="visible-xs" aria-label="{{'Unused' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
<span ng-switch-when="unused-disconnected"><span class="hidden-xs" translate>Disconnected (Unused)</span><span class="visible-xs" aria-label="{{'Disconnected (Unused)' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
|
||||
</span>
|
||||
<span>{{deviceName(deviceCfg)}}</span>
|
||||
</h4>
|
||||
@@ -786,6 +788,12 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAllDevicesPause(true)" ng-if="isAtleastOneDevicePausedStateSetTo(false)">
|
||||
<span class="fas fa-pause"></span> <span translate>Pause All</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAllDevicesPause(false)" ng-if="isAtleastOneDevicePausedStateSetTo(true)">
|
||||
<span class="fas fa-play"></span> <span translate>Resume All</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="globalChanges()">
|
||||
<span class="fas fa-fw fa-info-circle"></span> <span translate>Recent Changes</span>
|
||||
</button>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<p translate>Copyright © 2014-2019 the following Contributors:</p>
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="contributor-list">
|
||||
Jakob Borg, Audrius Butkevicius, Simon Frei, Alexander Graf, Alexandre Viau, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, dependabot-preview[bot], Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alessandro G., Alex Xu, Aman Gupta, Andrew Dunham, Andrew Rabert, Andrey D, André Colomb, Anjan Momi, Antoine Lamielle, Aranjedeath, Arkadiusz Tymiński, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benno Fünfstück, Benny Ng, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Chris Tonkinson, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Graham Miln, Han Boetes, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jacob, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan Cross, Jose Manuel Delicado, Jörg Thalheim, Kalle Laine, Karol Różycki, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mark Pulford, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max Schulze, MaximAL, Maxime Thirouin, Michael Jephcote, Michael Tilli, Mike Boone, MikeLund, Mingxuan Lin, Nicholas Rishel, Nico Stapelbroek, Nicolas Braud-Santoni, Niels Peter Roest, Nils Jakobi, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Richard Hartmann, Robert Carosi, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Sacheendra Talluri, Scott Klupfel, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tomasz Wilczyński, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, Vladimir Rusinov, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, dependabot[bot], derekriemer, desbma, georgespatton, ghjklw, janost, jaseg, jelle van der Waa, klemens, marco-m, otbutz, perewa, rubenbe, wangguoliang, xjtdy888, 佛跳墙
|
||||
Jakob Borg, Audrius Butkevicius, Simon Frei, Alexander Graf, Alexandre Viau, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, dependabot-preview[bot], greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Alessandro G., Alex Xu, Aman Gupta, Andrew Dunham, Andrew Rabert, Andrey D, André Colomb, Anjan Momi, Antoine Lamielle, Aranjedeath, Arkadiusz Tymiński, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Chris Tonkinson, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Graham Miln, Han Boetes, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jacob, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan Cross, Jose Manuel Delicado, Jörg Thalheim, Kalle Laine, Karol Różycki, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max Schulze, MaximAL, Maxime Thirouin, Michael Jephcote, Michael Rienstra, Michael Tilli, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Nicholas Rishel, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Richard Hartmann, Robert Carosi, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Sacheendra Talluri, Scott Klupfel, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tomasz Wilczyński, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, Vladimir Rusinov, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, dependabot[bot], derekriemer, desbma, georgespatton, ghjklw, janost, jaseg, jelle van der Waa, klemens, marco-m, mv1005, otbutz, perewa, rubenbe, wangguoliang, xjtdy888, 佛跳墙
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
@@ -42,9 +42,8 @@ angular.module('syncthing.core')
|
||||
$scope.folderStats = {};
|
||||
$scope.progress = {};
|
||||
$scope.version = {};
|
||||
$scope.needed = [];
|
||||
$scope.neededCurrentPage = 1;
|
||||
$scope.neededPageSize = 10;
|
||||
$scope.needed = {}
|
||||
$scope.neededFolder = '';
|
||||
$scope.failed = {};
|
||||
$scope.localChanged = {};
|
||||
$scope.scanProgress = {};
|
||||
@@ -299,12 +298,12 @@ angular.module('syncthing.core')
|
||||
for (var folder in $scope.progress) {
|
||||
if (!(folder in progress)) {
|
||||
if ($scope.neededFolder === folder) {
|
||||
refreshNeed(folder);
|
||||
$scope.refreshNeed($scope.needed.page, $scope.needed.perpage);
|
||||
}
|
||||
} else if ($scope.neededFolder === folder) {
|
||||
for (file in $scope.progress[folder]) {
|
||||
if (!(file in progress[folder])) {
|
||||
refreshNeed(folder);
|
||||
$scope.refreshNeed($scope.needed.page, $scope.needed.perpage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -580,18 +579,16 @@ angular.module('syncthing.core')
|
||||
}).error($scope.emitHTTPError);
|
||||
}
|
||||
|
||||
function refreshNeed(folder) {
|
||||
$scope.refreshNeed = function (page, perpage) {
|
||||
if (!$scope.neededFolder) {
|
||||
return;
|
||||
}
|
||||
var url = urlbase + "/db/need?folder=" + encodeURIComponent(folder);
|
||||
url += "&page=" + $scope.neededCurrentPage;
|
||||
url += "&perpage=" + $scope.neededPageSize;
|
||||
var url = urlbase + "/db/need?folder=" + encodeURIComponent($scope.neededFolder);
|
||||
url += "&page=" + page;
|
||||
url += "&perpage=" + perpage;
|
||||
$http.get(url).success(function (data) {
|
||||
if ($scope.neededFolder === folder) {
|
||||
console.log("refreshNeed", folder, data);
|
||||
parseNeeded(data);
|
||||
}
|
||||
console.log("refreshNeed", $scope.neededFolder, data);
|
||||
parseNeeded(data);
|
||||
}).error($scope.emitHTTPError);
|
||||
}
|
||||
|
||||
@@ -611,6 +608,7 @@ angular.module('syncthing.core')
|
||||
}
|
||||
|
||||
function parseNeeded(data) {
|
||||
$scope.needed = data;
|
||||
var merged = [];
|
||||
data.progress.forEach(function (item) {
|
||||
item.type = "progress";
|
||||
@@ -627,7 +625,7 @@ angular.module('syncthing.core')
|
||||
item.action = needAction(item);
|
||||
merged.push(item);
|
||||
});
|
||||
$scope.needed = merged;
|
||||
$scope.needed.items = merged;
|
||||
}
|
||||
|
||||
function pathJoin(base, name) {
|
||||
@@ -682,16 +680,6 @@ angular.module('syncthing.core')
|
||||
});
|
||||
};
|
||||
|
||||
$scope.neededPageChanged = function (page) {
|
||||
$scope.neededCurrentPage = page;
|
||||
refreshNeed($scope.neededFolder);
|
||||
};
|
||||
|
||||
$scope.neededChangePageSize = function (perpage) {
|
||||
$scope.neededPageSize = perpage;
|
||||
refreshNeed($scope.neededFolder);
|
||||
};
|
||||
|
||||
$scope.refreshFailed = function (page, perpage) {
|
||||
if (!$scope.failed || !$scope.failed.folder) {
|
||||
return;
|
||||
@@ -938,8 +926,10 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.deviceStatus = function (deviceCfg) {
|
||||
var status = '';
|
||||
|
||||
if ($scope.deviceFolders(deviceCfg).length === 0) {
|
||||
return 'unused';
|
||||
status = 'unused-';
|
||||
}
|
||||
|
||||
if (typeof $scope.connections[deviceCfg.deviceID] === 'undefined') {
|
||||
@@ -947,27 +937,22 @@ angular.module('syncthing.core')
|
||||
}
|
||||
|
||||
if (deviceCfg.paused) {
|
||||
return 'paused';
|
||||
return status + 'paused';
|
||||
}
|
||||
|
||||
if ($scope.connections[deviceCfg.deviceID].connected) {
|
||||
if ($scope.completion[deviceCfg.deviceID] && $scope.completion[deviceCfg.deviceID]._total === 100) {
|
||||
return 'insync';
|
||||
return status + 'insync';
|
||||
} else {
|
||||
return 'syncing';
|
||||
}
|
||||
}
|
||||
|
||||
// Disconnected
|
||||
return 'disconnected';
|
||||
return status + 'disconnected';
|
||||
};
|
||||
|
||||
$scope.deviceClass = function (deviceCfg) {
|
||||
if ($scope.deviceFolders(deviceCfg).length === 0) {
|
||||
// Unused
|
||||
return 'warning';
|
||||
}
|
||||
|
||||
if (typeof $scope.connections[deviceCfg.deviceID] === 'undefined') {
|
||||
return 'info';
|
||||
}
|
||||
@@ -1603,6 +1588,24 @@ angular.module('syncthing.core')
|
||||
return devices;
|
||||
};
|
||||
|
||||
$scope.setAllDevicesPause = function (pause) {
|
||||
$scope.devices.forEach(function (cfg) {
|
||||
cfg.paused = pause;
|
||||
});
|
||||
$scope.config.devices = $scope.devices;
|
||||
$scope.saveConfig();
|
||||
}
|
||||
|
||||
$scope.isAtleastOneDevicePausedStateSetTo = function (pause) {
|
||||
for (var i = 0; i < $scope.devices.length; i++) {
|
||||
if ($scope.devices[i].paused == pause) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
$scope.errorList = function () {
|
||||
if (!$scope.errors) {
|
||||
return [];
|
||||
@@ -1825,7 +1828,7 @@ angular.module('syncthing.core')
|
||||
|
||||
$scope.saveFolder = function () {
|
||||
$('#editFolder').modal('hide');
|
||||
var folderCfg = $scope.currentFolder;
|
||||
var folderCfg = angular.copy($scope.currentFolder);
|
||||
folderCfg.devices = [];
|
||||
folderCfg.selectedDevices[$scope.myID] = true;
|
||||
for (var deviceID in folderCfg.selectedDevices) {
|
||||
@@ -2226,11 +2229,10 @@ angular.module('syncthing.core')
|
||||
|
||||
$scope.showNeed = function (folder) {
|
||||
$scope.neededFolder = folder;
|
||||
refreshNeed(folder);
|
||||
$scope.refreshNeed(1, 10);
|
||||
$('#needed').modal().one('hidden.bs.modal', function () {
|
||||
$scope.neededFolder = undefined;
|
||||
$scope.needed = undefined;
|
||||
$scope.neededCurrentPage = 1;
|
||||
$scope.neededFolder = '';
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2380,8 +2382,8 @@ angular.module('syncthing.core')
|
||||
$scope.bumpFile = function (folder, file) {
|
||||
var url = urlbase + "/db/prio?folder=" + encodeURIComponent(folder) + "&file=" + encodeURIComponent(file);
|
||||
// In order to get the right view of data in the response.
|
||||
url += "&page=" + $scope.neededCurrentPage;
|
||||
url += "&perpage=" + $scope.neededPageSize;
|
||||
url += "&page=" + $scope.needed.page;
|
||||
url += "&perpage=" + $scope.needed.perpage;
|
||||
$http.post(url).success(function (data) {
|
||||
if ($scope.neededFolder === folder) {
|
||||
console.log("bumpFile", folder, data);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<td>{{changeEvent.data.action}}</td>
|
||||
<td>{{changeEvent.data.type}}</td>
|
||||
<td class="no-overflow-ellipse">{{folderLabel(changeEvent.data.folder)}}</td>
|
||||
<td class="no-overflow-ellipse">{{changeEvent.data.path}}</td>
|
||||
<td class="file-path no-overflow-ellipse">{{changeEvent.data.path}}</td>
|
||||
<td class="no-overflow-ellipse">{{changeEvent.time | date:"yyyy-MM-dd HH:mm:ss"}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -46,6 +46,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" role="tab" id="ldapHeading" data-toggle="collapse" data-parent="#advancedAccordion" href="#ldapConfig" aria-expanded="false" aria-controls="ldapConfig" style="cursor: pointer;">
|
||||
<h4 class="panel-title" tabindex="0" translate>LDAP</h4>
|
||||
</div>
|
||||
<div id="ldapConfig" class="panel-collapse collapse" role="tabpanel" aria-labelledby="ldapHeading">
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div ng-repeat="(key, value) in advancedConfig.ldap" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
|
||||
<label for="ldapInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}</label>
|
||||
<div class="col-sm-8">
|
||||
<input ng-if="inputTypeFor(key, value) == 'list'" id="ldapInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.ldap[key]" ng-list />
|
||||
<input ng-if="inputTypeFor(key, value) != 'list'" id="ldapInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.ldap[key]" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default" ng-repeat="folder in advancedConfig.folders">
|
||||
<div class="panel-heading" role="tab" id="folder{{$index}}Heading" data-toggle="collapse" data-parent="#advancedAccordion" href="#folder{{$index}}Config" aria-expanded="false" aria-controls="folder{{$index}}Config" style="cursor: pointer;">
|
||||
<h4 ng-if="folder.label.length == 0" class="panel-title" tabindex="0">
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tr dir-paginate="file in localChanged.files | itemsPerPage: localChanged.perpage" current-page="localChanged.page" total-items="model[localChangedFolder].receiveOnlyTotalItems" pagination-id="localChanged">
|
||||
<td>{{file.name}}</td>
|
||||
<td class="file-path">{{file.name}}</td>
|
||||
<td><span ng-hide="file.type == 'DIRECTORY'">{{file.size | binary}}B</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<table class="table table-striped table-condensed">
|
||||
|
||||
<tr dir-paginate="f in needed | itemsPerPage: neededPageSize" current-page="neededCurrentPage" total-items="model[neededFolder].needTotalItems" pagination-id="needed">
|
||||
<tr dir-paginate="f in needed.items | itemsPerPage: needed.perpage" current-page="needed.page" total-items="model[neededFolder].needTotalItems" pagination-id="needed">
|
||||
|
||||
<!-- Icon -->
|
||||
<td class="small-data col-xs-2">
|
||||
@@ -56,10 +56,10 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<dir-pagination-controls on-page-change="neededPageChanged(newPageNumber)" pagination-id="needed"></dir-pagination-controls>
|
||||
<dir-pagination-controls on-page-change="refreshNeed(newPageNumber, needed.perpage)" pagination-id="needed" ></dir-pagination-controls>
|
||||
<ul class="pagination pull-right">
|
||||
<li ng-repeat="option in [10, 25, 50]" ng-class="{ active: neededPageSize == option }">
|
||||
<a href="#" ng-click="neededChangePageSize(option)">{{option}}</a>
|
||||
<li ng-repeat="option in [10, 25, 50]" ng-class="{ active: needed.perpage == option }">
|
||||
<a href="#" ng-click="refreshNeed(needed.page, option)">{{option}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tr dir-paginate="file in remoteNeed[folder].files | itemsPerPage: remoteNeed[folder].perpage" current-page="remoteNeed[folder].page" total-items="completion[remoteNeedDevice.deviceID][folder].needItems" pagination-id="'remoteNeed-' + folder">
|
||||
<td>{{file.name}}</td>
|
||||
<td class="file-path">{{file.name}}</td>
|
||||
<td><span ng-hide="file.type == 'DIRECTORY'">{{file.size | binary}}B</span></td>
|
||||
<td>{{file.modified | date:"yyyy-MM-dd HH:mm:ss"}}</td>
|
||||
<td ng-if="file.modifiedBy">{{friendlyNameFromShort(file.modifiedBy)}}</td>
|
||||
|
||||
@@ -11,16 +11,17 @@ import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ldap "github.com/go-ldap/ldap/v3"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
ldap "gopkg.in/ldap.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -130,10 +131,16 @@ func authStatic(username string, password string, configUser string, configPassw
|
||||
|
||||
func authLDAP(username string, password string, cfg config.LDAPConfiguration) bool {
|
||||
address := cfg.Address
|
||||
hostname, _, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
hostname = address
|
||||
}
|
||||
var connection *ldap.Conn
|
||||
var err error
|
||||
if cfg.Transport == config.LDAPTransportTLS {
|
||||
connection, err = ldap.DialTLS("tcp", address, &tls.Config{InsecureSkipVerify: cfg.InsecureSkipVerify})
|
||||
connection, err = ldap.DialTLS("tcp", address, &tls.Config{
|
||||
ServerName: hostname,
|
||||
InsecureSkipVerify: cfg.InsecureSkipVerify,
|
||||
})
|
||||
} else {
|
||||
connection, err = ldap.Dial("tcp", address)
|
||||
}
|
||||
@@ -159,6 +166,35 @@ func authLDAP(username string, password string, cfg config.LDAPConfiguration) bo
|
||||
return false
|
||||
}
|
||||
|
||||
if cfg.SearchFilter == "" && cfg.SearchBaseDN == "" {
|
||||
// We're done here.
|
||||
return true
|
||||
}
|
||||
|
||||
if cfg.SearchFilter == "" || cfg.SearchBaseDN == "" {
|
||||
l.Warnln("LDAP configuration: both searchFilter and searchBaseDN must be set, or neither.")
|
||||
return false
|
||||
}
|
||||
|
||||
// If a search filter and search base is set we do an LDAP search for
|
||||
// the user. If this matches precisely one user then we are good to go.
|
||||
// The search filter uses the same %s interpolation as the bind DN.
|
||||
|
||||
searchString := fmt.Sprintf(cfg.SearchFilter, username)
|
||||
const sizeLimit = 2 // we search for up to two users -- we only want to match one, so getting any number >1 is a failure.
|
||||
const timeLimit = 60 // Search for up to a minute...
|
||||
searchReq := ldap.NewSearchRequest(cfg.SearchBaseDN, ldap.ScopeWholeSubtree, ldap.DerefFindingBaseObj, sizeLimit, timeLimit, false, searchString, nil, nil)
|
||||
|
||||
res, err := connection.Search(searchReq)
|
||||
if err != nil {
|
||||
l.Warnln("LDAP Search:", err)
|
||||
return false
|
||||
}
|
||||
if len(res.Entries) != 1 {
|
||||
l.Infof("Wrong number of LDAP search results, %d != 1", len(res.Entries))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -7,18 +7,15 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/auto"
|
||||
"github.com/syncthing/syncthing/lib/api/auto"
|
||||
"github.com/syncthing/syncthing/lib/assets"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
)
|
||||
@@ -27,7 +24,7 @@ const themePrefix = "theme-assets/"
|
||||
|
||||
type staticsServer struct {
|
||||
assetDir string
|
||||
assets map[string][]byte
|
||||
assets map[string]string
|
||||
availableThemes []string
|
||||
|
||||
mut sync.RWMutex
|
||||
@@ -111,7 +108,7 @@ func (s *staticsServer) serveAsset(w http.ResponseWriter, r *http.Request) {
|
||||
if s.assetDir != "" {
|
||||
p := filepath.Join(s.assetDir, theme, filepath.FromSlash(file))
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
mtype := s.mimeTypeForFile(file)
|
||||
mtype := assets.MimeTypeForFile(file)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
@@ -127,7 +124,7 @@ func (s *staticsServer) serveAsset(w http.ResponseWriter, r *http.Request) {
|
||||
if s.assetDir != "" {
|
||||
p := filepath.Join(s.assetDir, config.DefaultTheme, filepath.FromSlash(file))
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
mtype := s.mimeTypeForFile(file)
|
||||
mtype := assets.MimeTypeForFile(file)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
@@ -144,40 +141,11 @@ func (s *staticsServer) serveAsset(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
etag := fmt.Sprintf("%d", modificationTime.Unix())
|
||||
w.Header().Set("Last-Modified", modificationTime.Format(http.TimeFormat))
|
||||
w.Header().Set("Etag", etag)
|
||||
|
||||
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil {
|
||||
if modificationTime.Equal(t) || modificationTime.Before(t) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if match := r.Header.Get("If-None-Match"); match != "" {
|
||||
if strings.Contains(match, etag) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
mtype := s.mimeTypeForFile(file)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
} else {
|
||||
// ungzip if browser not send gzip accepted header
|
||||
var gr *gzip.Reader
|
||||
gr, _ = gzip.NewReader(bytes.NewReader(bs))
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
gr.Close()
|
||||
}
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bs)))
|
||||
|
||||
w.Write(bs)
|
||||
assets.Serve(w, r, assets.Asset{
|
||||
ContentGz: bs,
|
||||
Filename: file,
|
||||
Modified: modificationTime,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *staticsServer) serveThemes(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -186,33 +154,6 @@ func (s *staticsServer) serveThemes(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *staticsServer) mimeTypeForFile(file string) string {
|
||||
// We use a built in table of the common types since the system
|
||||
// TypeByExtension might be unreliable. But if we don't know, we delegate
|
||||
// to the system. All our files are UTF-8.
|
||||
ext := filepath.Ext(file)
|
||||
switch ext {
|
||||
case ".htm", ".html":
|
||||
return "text/html; charset=utf-8"
|
||||
case ".css":
|
||||
return "text/css; charset=utf-8"
|
||||
case ".js":
|
||||
return "application/javascript; charset=utf-8"
|
||||
case ".json":
|
||||
return "application/json; charset=utf-8"
|
||||
case ".png":
|
||||
return "image/png"
|
||||
case ".ttf":
|
||||
return "application/x-font-ttf"
|
||||
case ".woff":
|
||||
return "application/x-font-woff"
|
||||
case ".svg":
|
||||
return "image/svg+xml; charset=utf-8"
|
||||
default:
|
||||
return mime.TypeByExtension(ext)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *staticsServer) setTheme(theme string) {
|
||||
s.mut.Lock()
|
||||
s.theme = theme
|
||||
|
||||
@@ -152,19 +152,19 @@ func TestAssetsDir(t *testing.T) {
|
||||
gw := gzip.NewWriter(buf)
|
||||
gw.Write([]byte("default"))
|
||||
gw.Close()
|
||||
def := buf.Bytes()
|
||||
def := buf.String()
|
||||
|
||||
buf = new(bytes.Buffer)
|
||||
gw = gzip.NewWriter(buf)
|
||||
gw.Write([]byte("foo"))
|
||||
gw.Close()
|
||||
foo := buf.Bytes()
|
||||
foo := buf.String()
|
||||
|
||||
e := &staticsServer{
|
||||
theme: "foo",
|
||||
mut: sync.NewRWMutex(),
|
||||
assetDir: "testdata",
|
||||
assets: map[string][]byte{
|
||||
assets: map[string]string{
|
||||
"foo/a": foo, // overridden in foo/a
|
||||
"foo/b": foo,
|
||||
"default/a": def, // overridden in default/a (but foo/a takes precedence)
|
||||
|
||||
1
lib/api/auto/.gitignore
vendored
Normal file
1
lib/api/auto/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
gui.files.go
|
||||
@@ -10,9 +10,10 @@ import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/auto"
|
||||
"github.com/syncthing/syncthing/lib/api/auto"
|
||||
)
|
||||
|
||||
func TestAssets(t *testing.T) {
|
||||
@@ -23,10 +24,10 @@ func TestAssets(t *testing.T) {
|
||||
}
|
||||
|
||||
var gr *gzip.Reader
|
||||
gr, _ = gzip.NewReader(bytes.NewReader(idx))
|
||||
idx, _ = ioutil.ReadAll(gr)
|
||||
gr, _ = gzip.NewReader(strings.NewReader(idx))
|
||||
html, _ := ioutil.ReadAll(gr)
|
||||
|
||||
if !bytes.Contains(idx, []byte("<html")) {
|
||||
if !bytes.Contains(html, []byte("<html")) {
|
||||
t.Fatal("No html in index.html")
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:generate go run ../../script/genassets.go -o gui.files.go ../../gui
|
||||
//go:generate go run ../../../script/genassets.go -o gui.files.go ../../../gui
|
||||
|
||||
// Package auto contains auto generated files for web assets.
|
||||
package auto
|
||||
97
lib/assets/assets.go
Normal file
97
lib/assets/assets.go
Normal file
@@ -0,0 +1,97 @@
|
||||
// Copyright (C) 2014-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 assets hold utilities for serving static assets.
|
||||
//
|
||||
// The actual assets live in auto subpackages instead of here,
|
||||
// because the set of assets varies per program.
|
||||
package assets
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Asset is the type of arguments to Serve.
|
||||
type Asset struct {
|
||||
ContentGz string // gzipped contents of asset.
|
||||
Filename string // Original filename, determines Content-Type.
|
||||
Modified time.Time // Determines ETag and Last-Modified.
|
||||
}
|
||||
|
||||
// Serve writes a gzipped asset to w.
|
||||
func Serve(w http.ResponseWriter, r *http.Request, asset Asset) {
|
||||
header := w.Header()
|
||||
|
||||
mtype := MimeTypeForFile(asset.Filename)
|
||||
if mtype != "" {
|
||||
header.Set("Content-Type", mtype)
|
||||
}
|
||||
|
||||
etag := fmt.Sprintf(`"%x"`, asset.Modified.Unix())
|
||||
header.Set("ETag", etag)
|
||||
header.Set("Last-Modified", asset.Modified.Format(http.TimeFormat))
|
||||
|
||||
t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since"))
|
||||
if err == nil && !asset.Modified.After(t) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
if r.Header.Get("If-None-Match") == etag {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
header.Set("Content-Encoding", "gzip")
|
||||
header.Set("Content-Length", strconv.Itoa(len(asset.ContentGz)))
|
||||
io.WriteString(w, asset.ContentGz)
|
||||
} else {
|
||||
// gunzip for browsers that don't want gzip.
|
||||
var gr *gzip.Reader
|
||||
gr, _ = gzip.NewReader(strings.NewReader(asset.ContentGz))
|
||||
io.Copy(w, gr)
|
||||
gr.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// MimeTypeForFile returns the appropriate MIME type for an asset,
|
||||
// based on the filename.
|
||||
//
|
||||
// We use a built in table of the common types since the system
|
||||
// TypeByExtension might be unreliable. But if we don't know, we delegate
|
||||
// to the system. All our text files are in UTF-8.
|
||||
func MimeTypeForFile(file string) string {
|
||||
ext := filepath.Ext(file)
|
||||
switch ext {
|
||||
case ".htm", ".html":
|
||||
return "text/html; charset=utf-8"
|
||||
case ".css":
|
||||
return "text/css; charset=utf-8"
|
||||
case ".js":
|
||||
return "application/javascript; charset=utf-8"
|
||||
case ".json":
|
||||
return "application/json; charset=utf-8"
|
||||
case ".png":
|
||||
return "image/png"
|
||||
case ".ttf":
|
||||
return "application/x-font-ttf"
|
||||
case ".woff":
|
||||
return "application/x-font-woff"
|
||||
case ".svg":
|
||||
return "image/svg+xml; charset=utf-8"
|
||||
default:
|
||||
return mime.TypeByExtension(ext)
|
||||
}
|
||||
}
|
||||
103
lib/assets/assets_test.go
Normal file
103
lib/assets/assets_test.go
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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 assets
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func compress(s string) string {
|
||||
var sb strings.Builder
|
||||
gz := gzip.NewWriter(&sb)
|
||||
|
||||
io.WriteString(gz, s)
|
||||
gz.Close()
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func decompress(p []byte) (out []byte) {
|
||||
r, err := gzip.NewReader(bytes.NewBuffer(p))
|
||||
if err == nil {
|
||||
out, err = ioutil.ReadAll(r)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func TestServe(t *testing.T) {
|
||||
indexHTML := `<html>Hello, world!</html>`
|
||||
indexGz := compress(indexHTML)
|
||||
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
Serve(w, r, Asset{
|
||||
ContentGz: indexGz,
|
||||
Filename: r.URL.Path[1:],
|
||||
Modified: time.Unix(0, 0),
|
||||
})
|
||||
}
|
||||
|
||||
for _, acceptGzip := range []bool{true, false} {
|
||||
r := httptest.NewRequest("GET", "http://localhost/index.html", nil)
|
||||
if acceptGzip {
|
||||
r.Header.Set("accept-encoding", "gzip, deflate")
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, r)
|
||||
res := w.Result()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
t.Fatalf("wanted OK, got status %d", res.StatusCode)
|
||||
}
|
||||
if ctype := res.Header.Get("Content-Type"); ctype != "text/html; charset=utf-8" {
|
||||
t.Errorf("unexpected Content-Type %q", ctype)
|
||||
}
|
||||
// ETags must be quoted ASCII strings:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
|
||||
if etag := res.Header.Get("ETag"); etag != `"0"` {
|
||||
t.Errorf("unexpected ETag %q", etag)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(res.Body)
|
||||
if acceptGzip {
|
||||
body = decompress(body)
|
||||
}
|
||||
if string(body) != indexHTML {
|
||||
t.Fatalf("unexpected content %q", body)
|
||||
}
|
||||
}
|
||||
|
||||
r := httptest.NewRequest("GET", "http://localhost/index.html", nil)
|
||||
r.Header.Set("if-none-match", `"0"`)
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, r)
|
||||
res := w.Result()
|
||||
|
||||
if res.StatusCode != http.StatusNotModified {
|
||||
t.Fatalf("wanted NotModified, got status %d", res.StatusCode)
|
||||
}
|
||||
|
||||
r = httptest.NewRequest("GET", "http://localhost/index.html", nil)
|
||||
r.Header.Set("if-modified-since", time.Now().Format(http.TimeFormat))
|
||||
w = httptest.NewRecorder()
|
||||
handler(w, r)
|
||||
res = w.Result()
|
||||
|
||||
if res.StatusCode != http.StatusNotModified {
|
||||
t.Fatalf("wanted NotModified, got status %d", res.StatusCode)
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
|
||||
var (
|
||||
// Injected by build script
|
||||
Program = "syncthing"
|
||||
Version = "unknown-dev"
|
||||
Host = "unknown"
|
||||
User = "unknown"
|
||||
@@ -72,11 +71,16 @@ func setBuildData() {
|
||||
|
||||
stamp, _ := strconv.Atoi(Stamp)
|
||||
Date = time.Unix(int64(stamp), 0)
|
||||
|
||||
date := Date.UTC().Format("2006-01-02 15:04:05 MST")
|
||||
LongVersion = fmt.Sprintf(`%s %s "%s" (%s %s-%s) %s@%s %s`, Program, Version, Codename, runtime.Version(), runtime.GOOS, runtime.GOARCH, User, Host, date)
|
||||
|
||||
if len(Tags) > 0 {
|
||||
LongVersion = fmt.Sprintf("%s [%s]", LongVersion, strings.Join(Tags, ", "))
|
||||
}
|
||||
LongVersion = LongVersionFor("syncthing")
|
||||
}
|
||||
|
||||
// LongVersionFor returns the long version string for the given program name.
|
||||
func LongVersionFor(program string) string {
|
||||
// This string and date format is essentially part of our external API. Never change it.
|
||||
date := Date.UTC().Format("2006-01-02 15:04:05 MST")
|
||||
v := fmt.Sprintf(`%s %s "%s" (%s %s-%s) %s@%s %s`, program, Version, Codename, runtime.Version(), runtime.GOOS, runtime.GOARCH, User, Host, date)
|
||||
if len(Tags) > 0 {
|
||||
v = fmt.Sprintf("%s [%s]", v, strings.Join(Tags, ", "))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
46
lib/config/blockpullorder.go
Normal file
46
lib/config/blockpullorder.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2020 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package config
|
||||
|
||||
type BlockPullOrder int
|
||||
|
||||
const (
|
||||
BlockPullOrderStandard BlockPullOrder = iota // default is standard
|
||||
BlockPullOrderRandom
|
||||
BlockPullOrderInOrder
|
||||
)
|
||||
|
||||
func (o BlockPullOrder) String() string {
|
||||
switch o {
|
||||
case BlockPullOrderStandard:
|
||||
return "standard"
|
||||
case BlockPullOrderRandom:
|
||||
return "random"
|
||||
case BlockPullOrderInOrder:
|
||||
return "inOrder"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (o BlockPullOrder) MarshalText() ([]byte, error) {
|
||||
return []byte(o.String()), nil
|
||||
}
|
||||
|
||||
func (o *BlockPullOrder) UnmarshalText(bs []byte) error {
|
||||
switch string(bs) {
|
||||
case "standard":
|
||||
*o = BlockPullOrderStandard
|
||||
case "random":
|
||||
*o = BlockPullOrderRandom
|
||||
case "inOrder":
|
||||
*o = BlockPullOrderInOrder
|
||||
default:
|
||||
*o = BlockPullOrderStandard
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -57,6 +57,9 @@ type FolderConfiguration struct {
|
||||
MarkerName string `xml:"markerName" json:"markerName"`
|
||||
CopyOwnershipFromParent bool `xml:"copyOwnershipFromParent" json:"copyOwnershipFromParent"`
|
||||
RawModTimeWindowS int `xml:"modTimeWindowS" json:"modTimeWindowS"`
|
||||
MaxConcurrentWrites int `xml:"maxConcurrentWrites" json:"maxConcurrentWrites" default:"2"`
|
||||
DisableFsync bool `xml:"disableFsync" json:"disableFsync"`
|
||||
BlockPullOrder BlockPullOrder `xml:"blockPullOrder" json:"blockPullOrder"`
|
||||
|
||||
cachedFilesystem fs.Filesystem
|
||||
cachedModTimeWindow time.Duration
|
||||
|
||||
@@ -11,6 +11,8 @@ type LDAPConfiguration struct {
|
||||
BindDN string `xml:"bindDN,omitempty" json:"bindDN"`
|
||||
Transport LDAPTransport `xml:"transport,omitempty" json:"transport"`
|
||||
InsecureSkipVerify bool `xml:"insecureSkipVerify,omitempty" json:"insecureSkipVerify" default:"false"`
|
||||
SearchBaseDN string `xml:"searchBaseDN,omitempty" json:"searchBaseDN"`
|
||||
SearchFilter string `xml:"searchFilter,omitempty" json:"searchFilter"`
|
||||
}
|
||||
|
||||
func (c LDAPConfiguration) Copy() LDAPConfiguration {
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
|
||||
package config
|
||||
|
||||
import "encoding/xml"
|
||||
import (
|
||||
"encoding/xml"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type VersioningConfiguration struct {
|
||||
Type string `xml:"type,attr" json:"type"`
|
||||
@@ -38,6 +41,9 @@ func (c *VersioningConfiguration) MarshalXML(e *xml.Encoder, start xml.StartElem
|
||||
for k, v := range c.Params {
|
||||
tmp.Params = append(tmp.Params, InternalParam{k, v})
|
||||
}
|
||||
sort.Slice(tmp.Params, func(a, b int) bool {
|
||||
return tmp.Params[a].Key < tmp.Params[b].Key
|
||||
})
|
||||
|
||||
return e.EncodeElement(tmp, start)
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ func (d *quicDialer) Dial(ctx context.Context, _ protocol.DeviceID, uri *url.URL
|
||||
stream, err := session.OpenStreamSync(ctx)
|
||||
if err != nil {
|
||||
// It's ok to close these, this does not close the underlying packetConn.
|
||||
_ = session.Close()
|
||||
_ = session.CloseWithError(1, err.Error())
|
||||
if createdConn != nil {
|
||||
_ = createdConn.Close()
|
||||
}
|
||||
|
||||
@@ -102,7 +102,9 @@ func (t *quicListener) serve(ctx context.Context) error {
|
||||
l.Infoln("Listen (BEP/quic):", err)
|
||||
return err
|
||||
}
|
||||
t.notifyAddressesChanged(t)
|
||||
defer listener.Close()
|
||||
defer t.clearAddresses(t)
|
||||
|
||||
l.Infof("QUIC listener (%v) starting", packetConn.LocalAddr())
|
||||
defer l.Infof("QUIC listener (%v) shutting down", packetConn.LocalAddr())
|
||||
@@ -145,7 +147,7 @@ func (t *quicListener) serve(ctx context.Context) error {
|
||||
cancel()
|
||||
if err != nil {
|
||||
l.Debugf("failed to accept stream from %s: %v", session.RemoteAddr(), err)
|
||||
_ = session.Close()
|
||||
_ = session.CloseWithError(1, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package connections
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
@@ -30,7 +31,7 @@ type quicTlsConn struct {
|
||||
|
||||
func (q *quicTlsConn) Close() error {
|
||||
sterr := q.Stream.Close()
|
||||
seerr := q.Session.Close()
|
||||
seerr := q.Session.CloseWithError(0, "closing")
|
||||
var pcerr error
|
||||
if q.createdConn != nil {
|
||||
pcerr = q.createdConn.Close()
|
||||
@@ -44,6 +45,24 @@ func (q *quicTlsConn) Close() error {
|
||||
return pcerr
|
||||
}
|
||||
|
||||
func (q *quicTlsConn) ConnectionState() tls.ConnectionState {
|
||||
qcs := q.Session.ConnectionState()
|
||||
return tls.ConnectionState{
|
||||
Version: qcs.Version,
|
||||
HandshakeComplete: qcs.HandshakeComplete,
|
||||
DidResume: qcs.DidResume,
|
||||
CipherSuite: qcs.CipherSuite,
|
||||
NegotiatedProtocol: qcs.NegotiatedProtocol,
|
||||
NegotiatedProtocolIsMutual: qcs.NegotiatedProtocolIsMutual,
|
||||
ServerName: qcs.ServerName,
|
||||
PeerCertificates: qcs.PeerCertificates,
|
||||
VerifiedChains: qcs.VerifiedChains,
|
||||
SignedCertificateTimestamps: qcs.SignedCertificateTimestamps,
|
||||
OCSPResponse: qcs.OCSPResponse,
|
||||
TLSUnique: qcs.TLSUnique,
|
||||
}
|
||||
}
|
||||
|
||||
// Sort available packet connections by ip address, preferring unspecified local address.
|
||||
func packetConnLess(i interface{}, j interface{}) bool {
|
||||
iIsUnspecified := false
|
||||
|
||||
@@ -57,10 +57,12 @@ func (t *relayListener) serve(ctx context.Context) error {
|
||||
defer clnt.Stop()
|
||||
t.mut.Unlock()
|
||||
|
||||
oldURI := clnt.URI()
|
||||
// Start with nil, so that we send a addresses changed notification as soon as we connect somewhere.
|
||||
var oldURI *url.URL
|
||||
|
||||
l.Infof("Relay listener (%v) starting", t)
|
||||
defer l.Infof("Relay listener (%v) shutting down", t)
|
||||
defer t.clearAddresses(t)
|
||||
|
||||
for {
|
||||
select {
|
||||
|
||||
@@ -46,8 +46,9 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
perDeviceWarningIntv = 15 * time.Minute
|
||||
tlsHandshakeTimeout = 10 * time.Second
|
||||
perDeviceWarningIntv = 15 * time.Minute
|
||||
tlsHandshakeTimeout = 10 * time.Second
|
||||
minConnectionReplaceAge = 10 * time.Second
|
||||
)
|
||||
|
||||
// From go/src/crypto/tls/cipher_suites.go
|
||||
@@ -276,7 +277,7 @@ func (s *service) handle(ctx context.Context) {
|
||||
ct, connected := s.model.Connection(remoteID)
|
||||
|
||||
// Lower priority is better, just like nice etc.
|
||||
if connected && ct.Priority() > c.priority {
|
||||
if connected && (ct.Priority() > c.priority || time.Since(ct.Statistics().StartedAt) > minConnectionReplaceAge) {
|
||||
l.Debugf("Switching connections %s (existing: %s new: %s)", remoteID, ct, c)
|
||||
} else if connected {
|
||||
// We should not already be connected to the other party. TODO: This
|
||||
@@ -564,11 +565,11 @@ func (s *service) createListener(factory listenerFactory, uri *url.URL) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *service) logListenAddressesChangedEvent(l genericListener) {
|
||||
func (s *service) logListenAddressesChangedEvent(l ListenerAddresses) {
|
||||
s.evLogger.Log(events.ListenAddressesChanged, map[string]interface{}{
|
||||
"address": l.URI(),
|
||||
"lan": l.LANAddresses(),
|
||||
"wan": l.WANAddresses(),
|
||||
"address": l.URI,
|
||||
"lan": l.LANAddresses,
|
||||
"wan": l.WANAddresses,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -174,6 +174,12 @@ type listenerFactory interface {
|
||||
Valid(config.Configuration) error
|
||||
}
|
||||
|
||||
type ListenerAddresses struct {
|
||||
URI *url.URL
|
||||
WANAddresses []*url.URL
|
||||
LANAddresses []*url.URL
|
||||
}
|
||||
|
||||
type genericListener interface {
|
||||
Serve()
|
||||
Stop()
|
||||
@@ -188,7 +194,7 @@ type genericListener interface {
|
||||
WANAddresses() []*url.URL
|
||||
LANAddresses() []*url.URL
|
||||
Error() error
|
||||
OnAddressesChanged(func(genericListener))
|
||||
OnAddressesChanged(func(ListenerAddresses))
|
||||
String() string
|
||||
Factory() listenerFactory
|
||||
NATType() string
|
||||
@@ -203,14 +209,28 @@ type Model interface {
|
||||
}
|
||||
|
||||
type onAddressesChangedNotifier struct {
|
||||
callbacks []func(genericListener)
|
||||
callbacks []func(ListenerAddresses)
|
||||
}
|
||||
|
||||
func (o *onAddressesChangedNotifier) OnAddressesChanged(callback func(genericListener)) {
|
||||
func (o *onAddressesChangedNotifier) OnAddressesChanged(callback func(ListenerAddresses)) {
|
||||
o.callbacks = append(o.callbacks, callback)
|
||||
}
|
||||
|
||||
func (o *onAddressesChangedNotifier) notifyAddressesChanged(l genericListener) {
|
||||
o.notifyAddresses(ListenerAddresses{
|
||||
URI: l.URI(),
|
||||
WANAddresses: l.WANAddresses(),
|
||||
LANAddresses: l.LANAddresses(),
|
||||
})
|
||||
}
|
||||
|
||||
func (o *onAddressesChangedNotifier) clearAddresses(l genericListener) {
|
||||
o.notifyAddresses(ListenerAddresses{
|
||||
URI: l.URI(),
|
||||
})
|
||||
}
|
||||
|
||||
func (o *onAddressesChangedNotifier) notifyAddresses(l ListenerAddresses) {
|
||||
for _, callback := range o.callbacks {
|
||||
callback(l)
|
||||
}
|
||||
|
||||
@@ -55,7 +55,9 @@ func (t *tcpListener) serve(ctx context.Context) error {
|
||||
l.Infoln("Listen (BEP/tcp):", err)
|
||||
return err
|
||||
}
|
||||
t.notifyAddressesChanged(t)
|
||||
defer listener.Close()
|
||||
defer t.clearAddresses(t)
|
||||
|
||||
l.Infof("TCP listener (%v) starting", listener.Addr())
|
||||
defer l.Infof("TCP listener (%v) shutting down", listener.Addr())
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
var files, oneFile, firstHalf, secondHalf []protocol.FileInfo
|
||||
var files, filesUpdated, oneFile, firstHalf, secondHalf, changed100, unchanged100 []protocol.FileInfo
|
||||
|
||||
func lazyInitBenchFiles() {
|
||||
if files != nil {
|
||||
@@ -36,6 +36,12 @@ func lazyInitBenchFiles() {
|
||||
firstHalf = files[:middle]
|
||||
secondHalf = files[middle:]
|
||||
oneFile = firstHalf[middle-1 : middle]
|
||||
|
||||
unchanged100 := files[100:200]
|
||||
changed100 := append([]protocol.FileInfo{}, unchanged100...)
|
||||
for i := range changed100 {
|
||||
changed100[i].Version = changed100[i].Version.Copy().Update(myID)
|
||||
}
|
||||
}
|
||||
|
||||
func getBenchFileSet() (*db.Lowlevel, *db.FileSet) {
|
||||
@@ -86,18 +92,43 @@ func BenchmarkUpdate100Changed(b *testing.B) {
|
||||
ldb, benchS := getBenchFileSet()
|
||||
defer ldb.Close()
|
||||
|
||||
unchanged := files[100:200]
|
||||
changed := append([]protocol.FileInfo{}, unchanged...)
|
||||
for i := range changed {
|
||||
changed[i].Version = changed[i].Version.Copy().Update(myID)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if i%2 == 0 {
|
||||
benchS.Update(protocol.LocalDeviceID, changed100)
|
||||
} else {
|
||||
benchS.Update(protocol.LocalDeviceID, unchanged100)
|
||||
}
|
||||
}
|
||||
|
||||
b.ReportAllocs()
|
||||
}
|
||||
|
||||
func setup10Remotes(benchS *db.FileSet) {
|
||||
idBase := remoteDevice1.String()[1:]
|
||||
first := 'J'
|
||||
for i := 0; i < 10; i++ {
|
||||
id, _ := protocol.DeviceIDFromString(fmt.Sprintf("%v%s", first+rune(i), idBase))
|
||||
if i%2 == 0 {
|
||||
benchS.Update(id, changed100)
|
||||
} else {
|
||||
benchS.Update(id, unchanged100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUpdate100Changed10Remotes(b *testing.B) {
|
||||
ldb, benchS := getBenchFileSet()
|
||||
defer ldb.Close()
|
||||
|
||||
setup10Remotes(benchS)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if i%2 == 0 {
|
||||
benchS.Update(protocol.LocalDeviceID, changed)
|
||||
benchS.Update(protocol.LocalDeviceID, changed100)
|
||||
} else {
|
||||
benchS.Update(protocol.LocalDeviceID, unchanged)
|
||||
benchS.Update(protocol.LocalDeviceID, unchanged100)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,18 +139,28 @@ func BenchmarkUpdate100ChangedRemote(b *testing.B) {
|
||||
ldb, benchS := getBenchFileSet()
|
||||
defer ldb.Close()
|
||||
|
||||
unchanged := files[100:200]
|
||||
changed := append([]protocol.FileInfo{}, unchanged...)
|
||||
for i := range changed {
|
||||
changed[i].Version = changed[i].Version.Copy().Update(myID)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if i%2 == 0 {
|
||||
benchS.Update(remoteDevice0, changed100)
|
||||
} else {
|
||||
benchS.Update(remoteDevice0, unchanged100)
|
||||
}
|
||||
}
|
||||
|
||||
b.ReportAllocs()
|
||||
}
|
||||
|
||||
func BenchmarkUpdate100ChangedRemote10Remotes(b *testing.B) {
|
||||
ldb, benchS := getBenchFileSet()
|
||||
defer ldb.Close()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if i%2 == 0 {
|
||||
benchS.Update(remoteDevice0, changed)
|
||||
benchS.Update(remoteDevice0, changed100)
|
||||
} else {
|
||||
benchS.Update(remoteDevice0, unchanged)
|
||||
benchS.Update(remoteDevice0, unchanged100)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,3 +328,19 @@ func BenchmarkGlobalTruncated(b *testing.B) {
|
||||
|
||||
b.ReportAllocs()
|
||||
}
|
||||
|
||||
func BenchmarkNeedCount(b *testing.B) {
|
||||
ldb, benchS := getBenchFileSet()
|
||||
defer ldb.Close()
|
||||
|
||||
benchS.Update(protocol.LocalDeviceID, changed100)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
snap := benchS.Snapshot()
|
||||
_ = snap.NeedSize(protocol.LocalDeviceID)
|
||||
snap.Release()
|
||||
}
|
||||
|
||||
b.ReportAllocs()
|
||||
}
|
||||
|
||||
@@ -13,17 +13,11 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
)
|
||||
|
||||
var blockFinder *BlockFinder
|
||||
|
||||
type BlockFinder struct {
|
||||
db *Lowlevel
|
||||
}
|
||||
|
||||
func NewBlockFinder(db *Lowlevel) *BlockFinder {
|
||||
if blockFinder != nil {
|
||||
return blockFinder
|
||||
}
|
||||
|
||||
return &BlockFinder{
|
||||
db: db,
|
||||
}
|
||||
|
||||
@@ -481,3 +481,116 @@ func TestCheckGlobals(t *testing.T) {
|
||||
t.Error("Expected key missing error, got", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTo10(t *testing.T) {
|
||||
ldb, err := openJSONS("./testdata/v1.4.0-updateTo10.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
db := NewLowlevel(ldb)
|
||||
defer db.Close()
|
||||
|
||||
UpdateSchema(db)
|
||||
|
||||
folder := "test"
|
||||
|
||||
meta := db.getMetaAndCheck(folder)
|
||||
|
||||
empty := Counts{}
|
||||
|
||||
c := meta.Counts(protocol.LocalDeviceID, needFlag)
|
||||
if c.Files != 1 {
|
||||
t.Error("Expected 1 needed file locally, got", c.Files)
|
||||
}
|
||||
c.Files = 0
|
||||
if c.Deleted != 1 {
|
||||
t.Error("Expected 1 needed deletion locally, got", c.Deleted)
|
||||
}
|
||||
c.Deleted = 0
|
||||
if !c.Equal(empty) {
|
||||
t.Error("Expected all counts to be zero, got", c)
|
||||
}
|
||||
c = meta.Counts(remoteDevice0, needFlag)
|
||||
if !c.Equal(empty) {
|
||||
t.Error("Expected all counts to be zero, got", c)
|
||||
}
|
||||
|
||||
trans, err := db.newReadOnlyTransaction()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer trans.Release()
|
||||
// a
|
||||
vl, err := trans.getGlobalVersions(nil, []byte(folder), []byte("a"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, v := range vl.Versions {
|
||||
if !v.Deleted {
|
||||
t.Error("Unexpected undeleted global version for a")
|
||||
}
|
||||
}
|
||||
// b
|
||||
vl, err = trans.getGlobalVersions(nil, []byte(folder), []byte("b"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !vl.Versions[0].Deleted {
|
||||
t.Error("vl.Versions[0] not deleted for b")
|
||||
}
|
||||
if vl.Versions[1].Deleted {
|
||||
t.Error("vl.Versions[1] deleted for b")
|
||||
}
|
||||
// c
|
||||
vl, err = trans.getGlobalVersions(nil, []byte(folder), []byte("c"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if vl.Versions[0].Deleted {
|
||||
t.Error("vl.Versions[0] deleted for c")
|
||||
}
|
||||
if !vl.Versions[1].Deleted {
|
||||
t.Error("vl.Versions[1] not deleted for c")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropDuplicates(t *testing.T) {
|
||||
names := []string{
|
||||
"foo",
|
||||
"bar",
|
||||
"dcxvoijnds",
|
||||
"3d/dsfase/4/ss2",
|
||||
}
|
||||
tcs := []struct{ in, out []int }{
|
||||
{[]int{0}, []int{0}},
|
||||
{[]int{0, 1}, []int{0, 1}},
|
||||
{[]int{0, 1, 0, 1}, []int{0, 1}},
|
||||
{[]int{0, 1, 1, 1, 1}, []int{0, 1}},
|
||||
{[]int{0, 0, 0, 1}, []int{0, 1}},
|
||||
{[]int{0, 1, 2, 3}, []int{0, 1, 2, 3}},
|
||||
{[]int{3, 2, 1, 0, 0, 1, 2, 3}, []int{0, 1, 2, 3}},
|
||||
{[]int{0, 1, 1, 3, 0, 1, 0, 1, 2, 3}, []int{0, 1, 2, 3}},
|
||||
}
|
||||
|
||||
for tci, tc := range tcs {
|
||||
inp := make([]protocol.FileInfo, len(tc.in))
|
||||
expSeq := make(map[string]int)
|
||||
for i, j := range tc.in {
|
||||
inp[i] = protocol.FileInfo{Name: names[j], Sequence: int64(i)}
|
||||
expSeq[names[j]] = i
|
||||
}
|
||||
outp := normalizeFilenamesAndDropDuplicates(inp)
|
||||
if len(outp) != len(tc.out) {
|
||||
t.Errorf("tc %v: Expected %v entries, got %v", tci, len(tc.out), len(outp))
|
||||
continue
|
||||
}
|
||||
for i, f := range outp {
|
||||
if exp := names[tc.out[i]]; exp != f.Name {
|
||||
t.Errorf("tc %v: Got file %v at pos %v, expected %v", tci, f.Name, i, exp)
|
||||
}
|
||||
if exp := int64(expSeq[outp[i].Name]); exp != f.Sequence {
|
||||
t.Errorf("tc %v: Got sequence %v at pos %v, expected %v", tci, f.Sequence, i, exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,9 @@ const (
|
||||
|
||||
// KeyTypeBlockList <block list hash> = BlockList
|
||||
KeyTypeBlockList = 13
|
||||
|
||||
// KeyTypeBlockListMap <int32 folder ID> <block list hash> <file name> = <nothing>
|
||||
KeyTypeBlockListMap = 14
|
||||
)
|
||||
|
||||
type keyer interface {
|
||||
@@ -79,6 +82,8 @@ type keyer interface {
|
||||
// block map key stuff (former BlockMap)
|
||||
GenerateBlockMapKey(key, folder, hash, name []byte) (blockMapKey, error)
|
||||
NameFromBlockMapKey(key []byte) []byte
|
||||
GenerateBlockListMapKey(key, folder, hash, name []byte) (blockListMapKey, error)
|
||||
NameFromBlockListMapKey(key []byte) []byte
|
||||
|
||||
// file need index
|
||||
GenerateNeedFileKey(key, folder, name []byte) (needFileKey, error)
|
||||
@@ -203,6 +208,29 @@ func (k blockMapKey) WithoutHashAndName() []byte {
|
||||
return k[:keyPrefixLen+keyFolderLen]
|
||||
}
|
||||
|
||||
type blockListMapKey []byte
|
||||
|
||||
func (k defaultKeyer) GenerateBlockListMapKey(key, folder, hash, name []byte) (blockListMapKey, error) {
|
||||
folderID, err := k.folderIdx.ID(folder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key = resize(key, keyPrefixLen+keyFolderLen+keyHashLen+len(name))
|
||||
key[0] = KeyTypeBlockListMap
|
||||
binary.BigEndian.PutUint32(key[keyPrefixLen:], folderID)
|
||||
copy(key[keyPrefixLen+keyFolderLen:], hash)
|
||||
copy(key[keyPrefixLen+keyFolderLen+keyHashLen:], name)
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func (k defaultKeyer) NameFromBlockListMapKey(key []byte) []byte {
|
||||
return key[keyPrefixLen+keyFolderLen+keyHashLen:]
|
||||
}
|
||||
|
||||
func (k blockListMapKey) WithoutHashAndName() []byte {
|
||||
return k[:keyPrefixLen+keyFolderLen]
|
||||
}
|
||||
|
||||
type needFileKey []byte
|
||||
|
||||
func (k needFileKey) WithoutName() []byte {
|
||||
|
||||
@@ -8,14 +8,16 @@ package db
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/greatroar/blobloom"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/willf/bloom"
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
"github.com/thejerf/suture"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -25,53 +27,77 @@ const (
|
||||
// than 100k. For fewer than 100k items we will just get better false
|
||||
// positive rate instead.
|
||||
indirectGCBloomCapacity = 100000
|
||||
indirectGCBloomFalsePositiveRate = 0.01 // 1%
|
||||
indirectGCBloomFalsePositiveRate = 0.01 // 1%
|
||||
indirectGCBloomMaxBytes = 32 << 20 // Use at most 32MiB memory, which covers our desired FP rate at 27 M items
|
||||
indirectGCDefaultInterval = 13 * time.Hour
|
||||
indirectGCTimeKey = "lastIndirectGCTime"
|
||||
|
||||
// Use indirection for the block list when it exceeds this many entries
|
||||
blocksIndirectionCutoff = 3
|
||||
|
||||
recheckDefaultInterval = 30 * 24 * time.Hour
|
||||
)
|
||||
|
||||
var indirectGCInterval = indirectGCDefaultInterval
|
||||
|
||||
func init() {
|
||||
if dur, err := time.ParseDuration(os.Getenv("STGCINDIRECTEVERY")); err == nil {
|
||||
indirectGCInterval = dur
|
||||
}
|
||||
}
|
||||
|
||||
// Lowlevel is the lowest level database interface. It has a very simple
|
||||
// purpose: hold the actual backend database, and the in-memory state
|
||||
// that belong to that database. In the same way that a single on disk
|
||||
// database can only be opened once, there should be only one Lowlevel for
|
||||
// any given backend.
|
||||
type Lowlevel struct {
|
||||
*suture.Supervisor
|
||||
backend.Backend
|
||||
folderIdx *smallIndex
|
||||
deviceIdx *smallIndex
|
||||
keyer keyer
|
||||
gcMut sync.RWMutex
|
||||
gcKeyCount int
|
||||
gcStop chan struct{}
|
||||
folderIdx *smallIndex
|
||||
deviceIdx *smallIndex
|
||||
keyer keyer
|
||||
gcMut sync.RWMutex
|
||||
gcKeyCount int
|
||||
indirectGCInterval time.Duration
|
||||
recheckInterval time.Duration
|
||||
}
|
||||
|
||||
func NewLowlevel(backend backend.Backend) *Lowlevel {
|
||||
func NewLowlevel(backend backend.Backend, opts ...Option) *Lowlevel {
|
||||
db := &Lowlevel{
|
||||
Backend: backend,
|
||||
folderIdx: newSmallIndex(backend, []byte{KeyTypeFolderIdx}),
|
||||
deviceIdx: newSmallIndex(backend, []byte{KeyTypeDeviceIdx}),
|
||||
gcMut: sync.NewRWMutex(),
|
||||
gcStop: make(chan struct{}),
|
||||
Supervisor: suture.New("db.Lowlevel", suture.Spec{
|
||||
// Only log restarts in debug mode.
|
||||
Log: func(line string) {
|
||||
l.Debugln(line)
|
||||
},
|
||||
PassThroughPanics: true,
|
||||
}),
|
||||
Backend: backend,
|
||||
folderIdx: newSmallIndex(backend, []byte{KeyTypeFolderIdx}),
|
||||
deviceIdx: newSmallIndex(backend, []byte{KeyTypeDeviceIdx}),
|
||||
gcMut: sync.NewRWMutex(),
|
||||
indirectGCInterval: indirectGCDefaultInterval,
|
||||
recheckInterval: recheckDefaultInterval,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(db)
|
||||
}
|
||||
db.keyer = newDefaultKeyer(db.folderIdx, db.deviceIdx)
|
||||
go db.gcRunner()
|
||||
db.Add(util.AsService(db.gcRunner, "db.Lowlevel/gcRunner"))
|
||||
return db
|
||||
}
|
||||
|
||||
func (db *Lowlevel) Close() error {
|
||||
close(db.gcStop)
|
||||
return db.Backend.Close()
|
||||
type Option func(*Lowlevel)
|
||||
|
||||
// WithRecheckInterval sets the time interval in between metadata recalculations
|
||||
// and consistency checks.
|
||||
func WithRecheckInterval(dur time.Duration) Option {
|
||||
return func(db *Lowlevel) {
|
||||
if dur > 0 {
|
||||
db.recheckInterval = dur
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithIndirectGCInterval sets the time interval in between GC runs.
|
||||
func WithIndirectGCInterval(dur time.Duration) Option {
|
||||
return func(db *Lowlevel) {
|
||||
if dur > 0 {
|
||||
db.indirectGCInterval = dur
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ListFolders returns the list of folders currently in the database
|
||||
@@ -169,9 +195,10 @@ func (db *Lowlevel) updateLocalFiles(folder []byte, fs []protocol.FileInfo, meta
|
||||
if ok && unchanged(f, ef) {
|
||||
continue
|
||||
}
|
||||
blocksHashSame := ok && bytes.Equal(ef.BlocksHash, f.BlocksHash)
|
||||
|
||||
if ok {
|
||||
if !ef.IsDirectory() && !ef.IsDeleted() && !ef.IsInvalid() {
|
||||
if len(ef.Blocks) != 0 && !ef.IsInvalid() && ef.Size > 0 {
|
||||
for _, block := range ef.Blocks {
|
||||
keyBuf, err = db.keyer.GenerateBlockMapKey(keyBuf, folder, block.Hash, name)
|
||||
if err != nil {
|
||||
@@ -181,6 +208,15 @@ func (db *Lowlevel) updateLocalFiles(folder []byte, fs []protocol.FileInfo, meta
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !blocksHashSame {
|
||||
keyBuf, err := db.keyer.GenerateBlockListMapKey(keyBuf, folder, ef.BlocksHash, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = t.Delete(keyBuf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keyBuf, err = db.keyer.GenerateSequenceKey(keyBuf, folder, ef.SequenceNo())
|
||||
@@ -223,7 +259,7 @@ func (db *Lowlevel) updateLocalFiles(folder []byte, fs []protocol.FileInfo, meta
|
||||
}
|
||||
l.Debugf("adding sequence; folder=%q sequence=%v %v", folder, f.Sequence, f.Name)
|
||||
|
||||
if !f.IsDirectory() && !f.IsDeleted() && !f.IsInvalid() {
|
||||
if len(f.Blocks) != 0 && !f.IsInvalid() && f.Size > 0 {
|
||||
for i, block := range f.Blocks {
|
||||
binary.BigEndian.PutUint32(blockBuf, uint32(i))
|
||||
keyBuf, err = db.keyer.GenerateBlockMapKey(keyBuf, folder, block.Hash, name)
|
||||
@@ -234,6 +270,15 @@ func (db *Lowlevel) updateLocalFiles(folder []byte, fs []protocol.FileInfo, meta
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !blocksHashSame {
|
||||
keyBuf, err := db.keyer.GenerateBlockListMapKey(keyBuf, folder, f.BlocksHash, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = t.Put(keyBuf, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := t.Checkpoint(func() error {
|
||||
@@ -270,7 +315,7 @@ func (db *Lowlevel) dropFolder(folder []byte) error {
|
||||
}
|
||||
|
||||
// Remove all sequences related to the folder
|
||||
k1, err := db.keyer.GenerateSequenceKey(nil, folder, 0)
|
||||
k1, err := db.keyer.GenerateSequenceKey(k0, folder, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -279,7 +324,7 @@ func (db *Lowlevel) dropFolder(folder []byte) error {
|
||||
}
|
||||
|
||||
// Remove all items related to the given folder from the global bucket
|
||||
k2, err := db.keyer.GenerateGlobalVersionKey(nil, folder, nil)
|
||||
k2, err := db.keyer.GenerateGlobalVersionKey(k1, folder, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -288,7 +333,7 @@ func (db *Lowlevel) dropFolder(folder []byte) error {
|
||||
}
|
||||
|
||||
// Remove all needs related to the folder
|
||||
k3, err := db.keyer.GenerateNeedFileKey(nil, folder, nil)
|
||||
k3, err := db.keyer.GenerateNeedFileKey(k2, folder, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -297,7 +342,7 @@ func (db *Lowlevel) dropFolder(folder []byte) error {
|
||||
}
|
||||
|
||||
// Remove the blockmap of the folder
|
||||
k4, err := db.keyer.GenerateBlockMapKey(nil, folder, nil, nil)
|
||||
k4, err := db.keyer.GenerateBlockMapKey(k3, folder, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -305,6 +350,14 @@ func (db *Lowlevel) dropFolder(folder []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
k5, err := db.keyer.GenerateBlockListMapKey(k4, folder, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.deleteKeyPrefix(k5.WithoutHashAndName()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
@@ -357,6 +410,13 @@ func (db *Lowlevel) dropDeviceFolder(device, folder []byte, meta *metadataTracke
|
||||
if err := t.deleteKeyPrefix(key.WithoutHashAndName()); err != nil {
|
||||
return err
|
||||
}
|
||||
key2, err := db.keyer.GenerateBlockListMapKey(key, folder, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.deleteKeyPrefix(key2.WithoutHashAndName()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
@@ -494,12 +554,12 @@ func (db *Lowlevel) dropPrefix(prefix []byte) error {
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *Lowlevel) gcRunner() {
|
||||
func (db *Lowlevel) gcRunner(ctx context.Context) {
|
||||
// Calculate the time for the next GC run. Even if we should run GC
|
||||
// directly, give the system a while to get up and running and do other
|
||||
// stuff first. (We might have migrations and stuff which would be
|
||||
// better off running before GC.)
|
||||
next := db.timeUntil(indirectGCTimeKey, indirectGCInterval)
|
||||
next := db.timeUntil(indirectGCTimeKey, db.indirectGCInterval)
|
||||
if next < time.Minute {
|
||||
next = time.Minute
|
||||
}
|
||||
@@ -509,14 +569,14 @@ func (db *Lowlevel) gcRunner() {
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-db.gcStop:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-t.C:
|
||||
if err := db.gcIndirect(); err != nil {
|
||||
if err := db.gcIndirect(ctx); err != nil {
|
||||
l.Warnln("Database indirection GC failed:", err)
|
||||
}
|
||||
db.recordTime(indirectGCTimeKey)
|
||||
t.Reset(db.timeUntil(indirectGCTimeKey, indirectGCInterval))
|
||||
t.Reset(db.timeUntil(indirectGCTimeKey, db.indirectGCInterval))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -541,7 +601,7 @@ func (db *Lowlevel) timeUntil(key string, every time.Duration) time.Duration {
|
||||
return sleepTime
|
||||
}
|
||||
|
||||
func (db *Lowlevel) gcIndirect() error {
|
||||
func (db *Lowlevel) gcIndirect(ctx context.Context) error {
|
||||
// The indirection GC uses bloom filters to track used block lists and
|
||||
// versions. This means iterating over all items, adding their hashes to
|
||||
// the filter, then iterating over the indirected items and removing
|
||||
@@ -570,7 +630,11 @@ func (db *Lowlevel) gcIndirect() error {
|
||||
if db.gcKeyCount > capacity {
|
||||
capacity = db.gcKeyCount
|
||||
}
|
||||
blockFilter := bloom.NewWithEstimates(uint(capacity), indirectGCBloomFalsePositiveRate)
|
||||
blockFilter := blobloom.NewOptimized(blobloom.Config{
|
||||
Capacity: uint64(capacity),
|
||||
FPRate: indirectGCBloomFalsePositiveRate,
|
||||
MaxBits: 8 * indirectGCBloomMaxBytes,
|
||||
})
|
||||
|
||||
// Iterate the FileInfos, unmarshal the block and version hashes and
|
||||
// add them to the filter.
|
||||
@@ -581,12 +645,18 @@ func (db *Lowlevel) gcIndirect() error {
|
||||
}
|
||||
defer it.Release()
|
||||
for it.Next() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
var bl BlocksHashOnly
|
||||
if err := bl.Unmarshal(it.Value()); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(bl.BlocksHash) > 0 {
|
||||
blockFilter.Add(bl.BlocksHash)
|
||||
blockFilter.Add(bloomHash(bl.BlocksHash))
|
||||
}
|
||||
}
|
||||
it.Release()
|
||||
@@ -604,8 +674,14 @@ func (db *Lowlevel) gcIndirect() error {
|
||||
defer it.Release()
|
||||
matchedBlocks := 0
|
||||
for it.Next() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
key := blockListKey(it.Key())
|
||||
if blockFilter.Test(key.BlocksHash()) {
|
||||
if blockFilter.Has(bloomHash(key.BlocksHash())) {
|
||||
matchedBlocks++
|
||||
continue
|
||||
}
|
||||
@@ -628,6 +704,12 @@ func (db *Lowlevel) gcIndirect() error {
|
||||
return db.Compact()
|
||||
}
|
||||
|
||||
// Hash function for the bloomfilter: first eight bytes of the SHA-256.
|
||||
// Big or little-endian makes no difference, as long as we're consistent.
|
||||
func bloomHash(key []byte) uint64 {
|
||||
return binary.BigEndian.Uint64(key)
|
||||
}
|
||||
|
||||
// CheckRepair checks folder metadata and sequences for miscellaneous errors.
|
||||
func (db *Lowlevel) CheckRepair() {
|
||||
for _, folder := range db.ListFolders() {
|
||||
@@ -670,7 +752,7 @@ func (db *Lowlevel) loadMetadataTracker(folder string) *metadataTracker {
|
||||
return db.getMetaAndCheck(folder)
|
||||
}
|
||||
|
||||
if age := time.Since(meta.Created()); age > databaseRecheckInterval {
|
||||
if age := time.Since(meta.Created()); age > db.recheckInterval {
|
||||
l.Infof("Stored folder metadata for %q is %v old; recalculating", folder, age)
|
||||
return db.getMetaAndCheck(folder)
|
||||
}
|
||||
@@ -700,6 +782,25 @@ func (db *Lowlevel) recalcMeta(folder string) (*metadataTracker, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
meta.emptyNeeded(protocol.LocalDeviceID)
|
||||
err = t.withNeed([]byte(folder), protocol.LocalDeviceID[:], true, func(f FileIntf) bool {
|
||||
meta.addNeeded(protocol.LocalDeviceID, f)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, device := range meta.devices() {
|
||||
meta.emptyNeeded(device)
|
||||
err = t.withNeed([]byte(folder), device[:], true, func(f FileIntf) bool {
|
||||
meta.addNeeded(device, f)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
meta.SetCreated()
|
||||
if err := meta.toDB(t, []byte(folder)); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -32,6 +32,8 @@ type metaKey struct {
|
||||
flag uint32
|
||||
}
|
||||
|
||||
const needFlag uint32 = 1 << 31 // Last bit, as early ones are local flags
|
||||
|
||||
func newMetadataTracker() *metadataTracker {
|
||||
return &metadataTracker{
|
||||
mut: sync.NewRWMutex(),
|
||||
@@ -116,10 +118,33 @@ func (m *metadataTracker) countsPtr(dev protocol.DeviceID, flag uint32) *Counts
|
||||
idx = len(m.counts.Counts)
|
||||
m.counts.Counts = append(m.counts.Counts, Counts{DeviceID: dev[:], LocalFlags: flag})
|
||||
m.indexes[key] = idx
|
||||
// Need bucket must be initialized when a device first occurs in
|
||||
// the metadatatracker, even if there's no change to the need
|
||||
// bucket itself.
|
||||
nkey := metaKey{dev, needFlag}
|
||||
nidx, ok := m.indexes[nkey]
|
||||
if !ok {
|
||||
// Initially a new device needs everything, except deletes
|
||||
nidx = len(m.counts.Counts)
|
||||
m.counts.Counts = append(m.counts.Counts, m.allNeededCounts(dev))
|
||||
m.indexes[nkey] = nidx
|
||||
}
|
||||
}
|
||||
return &m.counts.Counts[idx]
|
||||
}
|
||||
|
||||
// allNeeded makes sure there is a counts in case the device needs everything.
|
||||
func (m *countsMap) allNeededCounts(dev protocol.DeviceID) Counts {
|
||||
counts := Counts{}
|
||||
if idx, ok := m.indexes[metaKey{protocol.GlobalDeviceID, 0}]; ok {
|
||||
counts = m.counts.Counts[idx]
|
||||
counts.Deleted = 0 // Don't need deletes if having nothing
|
||||
}
|
||||
counts.DeviceID = dev[:]
|
||||
counts.LocalFlags = needFlag
|
||||
return counts
|
||||
}
|
||||
|
||||
// addFile adds a file to the counts, adjusting the sequence number as
|
||||
// appropriate
|
||||
func (m *metadataTracker) addFile(dev protocol.DeviceID, f FileIntf) {
|
||||
@@ -146,6 +171,30 @@ func (m *metadataTracker) addFile(dev protocol.DeviceID, f FileIntf) {
|
||||
}
|
||||
}
|
||||
|
||||
// emptyNeeded makes sure there is a zero counts in case the device needs nothing.
|
||||
func (m *metadataTracker) emptyNeeded(dev protocol.DeviceID) {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
m.dirty = true
|
||||
|
||||
m.indexes[metaKey{dev, needFlag}] = len(m.counts.Counts)
|
||||
m.counts.Counts = append(m.counts.Counts, Counts{
|
||||
DeviceID: dev[:],
|
||||
LocalFlags: needFlag,
|
||||
})
|
||||
}
|
||||
|
||||
// addNeeded adds a file to the needed counts
|
||||
func (m *metadataTracker) addNeeded(dev protocol.DeviceID, f FileIntf) {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
m.dirty = true
|
||||
|
||||
m.addFileLocked(dev, needFlag, f)
|
||||
}
|
||||
|
||||
func (m *metadataTracker) Sequence(dev protocol.DeviceID) int64 {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
@@ -200,6 +249,16 @@ func (m *metadataTracker) removeFile(dev protocol.DeviceID, f FileIntf) {
|
||||
}
|
||||
}
|
||||
|
||||
// removeNeeded removes a file from the needed counts
|
||||
func (m *metadataTracker) removeNeeded(dev protocol.DeviceID, f FileIntf) {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
m.dirty = true
|
||||
|
||||
m.removeFileLocked(dev, needFlag, f)
|
||||
}
|
||||
|
||||
func (m *metadataTracker) removeFileLocked(dev protocol.DeviceID, flag uint32, f FileIntf) {
|
||||
cp := m.countsPtr(dev, flag)
|
||||
|
||||
@@ -277,21 +336,17 @@ func (m *countsMap) Counts(dev protocol.DeviceID, flag uint32) Counts {
|
||||
|
||||
idx, ok := m.indexes[metaKey{dev, flag}]
|
||||
if !ok {
|
||||
if flag == needFlag {
|
||||
// If there's nothing about a device in the index yet,
|
||||
// it needs everything.
|
||||
return m.allNeededCounts(dev)
|
||||
}
|
||||
return Counts{}
|
||||
}
|
||||
|
||||
return m.counts.Counts[idx]
|
||||
}
|
||||
|
||||
// Counts returns the counts for the given device ID and flag. `flag` should
|
||||
// be zero or have exactly one bit set.
|
||||
func (m *metadataTracker) Counts(dev protocol.DeviceID, flag uint32) Counts {
|
||||
m.mut.RLock()
|
||||
defer m.mut.RUnlock()
|
||||
|
||||
return m.countsMap.Counts(dev, flag)
|
||||
}
|
||||
|
||||
// Snapshot returns a copy of the metadata for reading.
|
||||
func (m *metadataTracker) Snapshot() *countsMap {
|
||||
m.mut.RLock()
|
||||
|
||||
@@ -175,3 +175,9 @@ func TestRecalcMeta(t *testing.T) {
|
||||
t.Fatalf("Wrong fixed global byte count, %d != 3000", gs.Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetaKeyCollisions(t *testing.T) {
|
||||
if protocol.LocalAllFlags&needFlag != 0 {
|
||||
t.Error("Collision between need flag and protocol local file flags")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,21 +16,16 @@ import (
|
||||
// NamespacedKV is a simple key-value store using a specific namespace within
|
||||
// a leveldb.
|
||||
type NamespacedKV struct {
|
||||
db *Lowlevel
|
||||
prefix []byte
|
||||
db backend.Backend
|
||||
prefix string
|
||||
}
|
||||
|
||||
// NewNamespacedKV returns a new NamespacedKV that lives in the namespace
|
||||
// specified by the prefix.
|
||||
func NewNamespacedKV(db *Lowlevel, prefix string) *NamespacedKV {
|
||||
prefixBs := []byte(prefix)
|
||||
// After the conversion from string the cap will be larger than the len (in Go 1.11.5,
|
||||
// 32 bytes cap for small strings). We need to cut it down to ensure append() calls
|
||||
// on the prefix make a new allocation.
|
||||
prefixBs = prefixBs[:len(prefixBs):len(prefixBs)]
|
||||
func NewNamespacedKV(db backend.Backend, prefix string) *NamespacedKV {
|
||||
return &NamespacedKV{
|
||||
db: db,
|
||||
prefix: prefixBs,
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +125,7 @@ func (n NamespacedKV) Delete(key string) error {
|
||||
}
|
||||
|
||||
func (n NamespacedKV) prefixedKey(key string) []byte {
|
||||
return append(n.prefix, []byte(key)...)
|
||||
return []byte(n.prefix + key)
|
||||
}
|
||||
|
||||
// Well known namespaces that can be instantiated without knowing the key
|
||||
@@ -138,18 +133,18 @@ func (n NamespacedKV) prefixedKey(key string) []byte {
|
||||
|
||||
// NewDeviceStatisticsNamespace creates a KV namespace for device statistics
|
||||
// for the given device.
|
||||
func NewDeviceStatisticsNamespace(db *Lowlevel, device string) *NamespacedKV {
|
||||
func NewDeviceStatisticsNamespace(db backend.Backend, device string) *NamespacedKV {
|
||||
return NewNamespacedKV(db, string(KeyTypeDeviceStatistic)+device)
|
||||
}
|
||||
|
||||
// NewFolderStatisticsNamespace creates a KV namespace for folder statistics
|
||||
// for the given folder.
|
||||
func NewFolderStatisticsNamespace(db *Lowlevel, folder string) *NamespacedKV {
|
||||
func NewFolderStatisticsNamespace(db backend.Backend, folder string) *NamespacedKV {
|
||||
return NewNamespacedKV(db, string(KeyTypeFolderStatistic)+folder)
|
||||
}
|
||||
|
||||
// NewMiscDateNamespace creates a KV namespace for miscellaneous metadata.
|
||||
func NewMiscDataNamespace(db *Lowlevel) *NamespacedKV {
|
||||
func NewMiscDataNamespace(db backend.Backend) *NamespacedKV {
|
||||
return NewNamespacedKV(db, string(KeyTypeMiscData))
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ func reset(n *NamespacedKV) {
|
||||
}
|
||||
defer tr.Release()
|
||||
|
||||
it, err := tr.NewPrefixIterator(n.prefix)
|
||||
it, err := tr.NewPrefixIterator([]byte(n.prefix))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -22,9 +22,10 @@ import (
|
||||
// 6: v0.14.50
|
||||
// 7: v0.14.53
|
||||
// 8-9: v1.4.0
|
||||
// 10-11: v1.6.0
|
||||
const (
|
||||
dbVersion = 9
|
||||
dbMinSyncthingVersion = "v1.4.0"
|
||||
dbVersion = 11
|
||||
dbMinSyncthingVersion = "v1.6.0"
|
||||
)
|
||||
|
||||
type databaseDowngradeError struct {
|
||||
@@ -84,7 +85,9 @@ func (db *schemaUpdater) updateSchema() error {
|
||||
{5, db.updateSchemaTo5},
|
||||
{6, db.updateSchema5to6},
|
||||
{7, db.updateSchema6to7},
|
||||
{9, db.updateSchemato9},
|
||||
{9, db.updateSchemaTo9},
|
||||
{10, db.updateSchemaTo10},
|
||||
{11, db.updateSchemaTo11},
|
||||
}
|
||||
|
||||
for _, m := range migrations {
|
||||
@@ -154,8 +157,10 @@ func (db *schemaUpdater) updateSchema0to1(_ int) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Purposely pass nil file name to remove from global list,
|
||||
// but don't touch meta and needs
|
||||
buf, err = t.removeFromGlobal(gk, buf, folder, device, nil, nil)
|
||||
if err != nil {
|
||||
if err != nil && err != errEntryFromGlobalMissing {
|
||||
return err
|
||||
}
|
||||
if err := t.Delete(dbi.Key()); err != nil {
|
||||
@@ -278,7 +283,12 @@ func (db *schemaUpdater) updateSchema2to3(_ int) error {
|
||||
if ok {
|
||||
v = haveFile.FileVersion()
|
||||
}
|
||||
if !need(f, ok, v) {
|
||||
fv := FileVersion{
|
||||
Version: f.FileVersion(),
|
||||
Invalid: f.IsInvalid(),
|
||||
Deleted: f.IsDeleted(),
|
||||
}
|
||||
if !need(fv, ok, v) {
|
||||
return true
|
||||
}
|
||||
nk, putErr = t.keyer.GenerateNeedFileKey(nk, folder, []byte(f.FileName()))
|
||||
@@ -390,7 +400,6 @@ func (db *schemaUpdater) updateSchema6to7(_ int) error {
|
||||
var delErr error
|
||||
err := t.withNeedLocal(folder, false, func(f FileIntf) bool {
|
||||
name := []byte(f.FileName())
|
||||
global := f.(protocol.FileInfo)
|
||||
gk, delErr = db.keyer.GenerateGlobalVersionKey(gk, folder, name)
|
||||
if delErr != nil {
|
||||
return false
|
||||
@@ -413,7 +422,13 @@ func (db *schemaUpdater) updateSchema6to7(_ int) error {
|
||||
// so lets not act on it.
|
||||
return true
|
||||
}
|
||||
if localFV, haveLocalFV := fl.Get(protocol.LocalDeviceID[:]); !need(global, haveLocalFV, localFV.Version) {
|
||||
globalFV := FileVersion{
|
||||
Version: f.FileVersion(),
|
||||
Invalid: f.IsInvalid(),
|
||||
Deleted: f.IsDeleted(),
|
||||
}
|
||||
|
||||
if localFV, haveLocalFV := fl.Get(protocol.LocalDeviceID[:]); !need(globalFV, haveLocalFV, localFV.Version) {
|
||||
key, err := t.keyer.GenerateNeedFileKey(nk, folder, name)
|
||||
if err != nil {
|
||||
delErr = err
|
||||
@@ -423,6 +438,9 @@ func (db *schemaUpdater) updateSchema6to7(_ int) error {
|
||||
}
|
||||
return delErr == nil
|
||||
})
|
||||
if delErr != nil {
|
||||
return delErr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -433,7 +451,7 @@ func (db *schemaUpdater) updateSchema6to7(_ int) error {
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchemato9(prev int) error {
|
||||
func (db *schemaUpdater) updateSchemaTo9(prev int) error {
|
||||
// Loads and rewrites all files with blocks, to deduplicate block lists.
|
||||
// Checks for missing or incorrect sequence entries and rewrites those.
|
||||
|
||||
@@ -481,3 +499,114 @@ func (db *schemaUpdater) updateSchemato9(prev int) error {
|
||||
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchemaTo10(_ int) error {
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
var buf []byte
|
||||
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
|
||||
buf, err = t.keyer.GenerateGlobalVersionKey(buf, folder, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf = globalVersionKey(buf).WithoutName()
|
||||
dbi, err := t.NewPrefixIterator(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dbi.Release()
|
||||
|
||||
for dbi.Next() {
|
||||
var vl VersionList
|
||||
if err := vl.Unmarshal(dbi.Value()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
changed := false
|
||||
name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
|
||||
|
||||
for i, fv := range vl.Versions {
|
||||
buf, err = t.keyer.GenerateDeviceFileKey(buf, folder, fv.Device, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, ok, err := t.getFileTrunc(buf, true)
|
||||
if !ok {
|
||||
return errEntryFromGlobalMissing
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f.IsDeleted() {
|
||||
vl.Versions[i].Deleted = true
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
if err := t.Put(dbi.Key(), mustMarshal(&vl)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.Checkpoint(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
dbi.Release()
|
||||
}
|
||||
|
||||
// Trigger metadata recalc
|
||||
if err := t.deleteKeyPrefix([]byte{KeyTypeFolderMeta}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
func (db *schemaUpdater) updateSchemaTo11(_ int) error {
|
||||
// Populates block list map for every folder.
|
||||
|
||||
t, err := db.newReadWriteTransaction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.close()
|
||||
|
||||
var dk []byte
|
||||
for _, folderStr := range db.ListFolders() {
|
||||
folder := []byte(folderStr)
|
||||
var putErr error
|
||||
err := t.withHave(folder, protocol.LocalDeviceID[:], nil, true, func(fi FileIntf) bool {
|
||||
f := fi.(FileInfoTruncated)
|
||||
if f.IsDirectory() || f.IsDeleted() || f.IsSymlink() || f.IsInvalid() || f.BlocksHash == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
name := []byte(f.FileName())
|
||||
dk, putErr = db.keyer.GenerateBlockListMapKey(dk, folder, f.BlocksHash, name)
|
||||
if putErr != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if putErr = t.Put(dk, nil); putErr != nil {
|
||||
return false
|
||||
}
|
||||
putErr = t.Checkpoint()
|
||||
return putErr == nil
|
||||
})
|
||||
if putErr != nil {
|
||||
return putErr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user