Compare commits

...
Author SHA1 Message Date
Jakob Borg 96b03fac04 chore: trivial lint fix 2025-05-20 14:34:20 +02:00
Jakob BorgandGitHub 085455d72e feat: add syncthing debug database-statistics command (#10117)
This adds a command that shows database statistics. Currently it
requires a fork of the sqlite package to add the dbstats virtual table;
the modernc variant already has it.

This also provides the canonical mapping between folder ID and database
file, for tinkerers...

```
% ./bin/syncthing debug database-statistics
DATABASE                 FOLDER ID    TABLE                                  SIZE     FILL
========                 ====== ==    =====                                  ====     ====
main.db                  -            folders                               4 KiB    8.4 %
main.db                  -            folders_database_name                 4 KiB    6.0 %
main.db                  -            kv                                    4 KiB   41.1 %
main.db                  -            schemamigrations                      4 KiB    3.9 %
main.db                  -            sqlite_autoindex_folders_1            4 KiB    3.7 %
...
folder.0007-txpxsvyd.db  w3ejt-fn4dm  indexids                              4 KiB    1.5 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  kv                                    4 KiB    0.8 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  mtimes                              608 KiB   81.5 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  schemamigrations                      4 KiB    3.9 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  sqlite_autoindex_blocklists_1      4108 KiB   89.5 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  sqlite_autoindex_blocks_1        700020 KiB   88.1 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  sqlite_autoindex_devices_1            4 KiB    3.6 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  sqlite_autoindex_kv_1                 4 KiB    0.6 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  sqlite_schema                        12 KiB   45.9 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  sqlite_sequence                       4 KiB    1.0 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  sqlite_stat1                          4 KiB   12.2 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  sqlite_stat4                          4 KiB    0.2 %
folder.0007-txpxsvyd.db  w3ejt-fn4dm  (total)                         1906020 KiB   92.8 %
main.db + children       -            (total)                         2205888 KiB   92.0 %
```
2025-05-20 14:27:08 +02:00
Jakob Borg 72849690c9 fix(model): index handler error handling 2025-05-20 14:26:14 +02:00
Jakob Borg f09cca52f2 Merge branch 'main' into v2
* main:
  build: reactivate golangci-lint (#10118)
  chore(gui): add Serbian (sr) translation template (#10116)
  chore(gui, man, authors): update docs, translations, and contributors
2025-05-20 14:05:29 +02:00
Jakob BorgandGitHub 9a3493c2f4 build: reactivate golangci-lint (#10118)
With DeepSource becoming (imho) less and less useful, let's get this one
back on track. It will likely require adjusting over time.
2025-05-20 14:03:43 +02:00
André ColombandGitHub fa404d5a0d chore(gui): add Serbian (sr) translation template (#10116)
Based on user request from Weblate, user `@vlazic`.
2025-05-19 21:06:38 +00:00
Syncthing Release Automation 73ad18fbfb chore(gui, man, authors): update docs, translations, and contributors 2025-05-19 03:56:31 +00:00
Jakob Borg a4db309b39 chore: refine author list generation
Now applies a slightly narrower definition of "author", being one that
has touched code in a file that exists today (tracking renames).
2025-05-17 16:56:56 +02:00
Jakob Borg 4bc17bc588 build: use Go 1.24.2 specifically
https://github.com/golang/go/issues/73617
2025-05-17 00:37:36 +02:00
Jakob BorgandGitHub 964c8d7d65 fix(model): correct bufferpool handling; simplify (#10113)
The copier routine refactor resulted in bad buffer pool handling,
putting a buffer back into the pool twice. This simplifies and removes
the danger prone Upgrade() method.
2025-05-16 22:50:13 +02:00
Jakob Borg bacf506e90 Merge branch 'main' into v2
* main:
  chore(gui, man, authors): update docs, translations, and contributors
  fix(config): mark audit log options as needing restart (fixes #10099) (#10100)
  fix(config): deep copy configuration defaults (fixes #9916) (#10101)
2025-05-16 16:17:43 +02:00
Syncthing Release Automation 1dd264894a chore(gui, man, authors): update docs, translations, and contributors 2025-05-12 03:54:02 +00:00
8c3d2f3bc5 fix(config): mark audit log options as needing restart (fixes #10099) (#10100)
### Testing

Change the `auditEnabled` option and you should get a prompt in the Web
GUI.
Restart and change the `auditFile` option, and you should get that same
prompt.

The prompt you should get is shown in the screenshots below.

### Screenshots


![Screenshot_20250507_122546](https://github.com/user-attachments/assets/23ce7c42-5e60-4f88-ac58-f312a9a1f5cc)

Co-authored-by: Jakob Borg <jakob@kastelo.net>
2025-05-09 10:49:11 +00:00
Hazem KrimiandGitHub 702ed8ecc1 fix(config): deep copy configuration defaults (fixes #9916) (#10101)
### Purpose

Setting default configuration was not working properly since the
defaults struct is not deeply copied.

### Testing

Try running commands to change default configuration and either inspect
`config.xml` or `/rest/config` result to see the applied changed.
Example:
```
./syncthing cli config defaults folder versioning params set keep 5
```
2025-05-09 07:40:32 +02:00
35 changed files with 450 additions and 434 deletions
+22 -2
View File
@@ -10,7 +10,7 @@ env:
# The go version to use for builds. We set check-latest to true when
# installing, so we get the latest patch version that matches the
# expression.
GO_VERSION: "~1.24.0"
GO_VERSION: "1.24.2"
# Optimize compatibility on the slow archictures.
GOMIPS: softfloat
@@ -22,7 +22,7 @@ env:
BUILD_USER: builder
BUILD_HOST: github.syncthing.net
TAGS: "netgo osusergo sqlite_omit_load_extension"
TAGS: "netgo osusergo sqlite_omit_load_extension sqlite_dbstat"
# A note on actions and third party code... The actions under actions/ (like
# `uses: actions/checkout`) are maintained by GitHub, and we need to trust
@@ -128,6 +128,7 @@ jobs:
- package-debian
- package-windows
- govulncheck
- golangci
steps:
- uses: actions/checkout@v4
@@ -1048,3 +1049,22 @@ jobs:
go run build.go assets
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
golangci:
runs-on: ubuntu-latest
name: Run golangci-lint
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
check-latest: true
- name: ensure asset generation
run: go run build.go assets
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
with:
only-new-issues: true
+35 -13
View File
@@ -1,45 +1,67 @@
version: "2"
linters:
enable-all: true
default: all
disable:
- cyclop
- depguard
- err113
- exhaustive
- exhaustruct
- forbidigo
- funlen
- gci
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
- gocyclo
- godot
- godox
- gofmt
- goimports
- gomoddirectives
- inamedparam
- interfacebloat
- ireturn
- lll
- maintidx
- mnd
- musttag
- nestif
- nlreturn
- nonamedreturns
- paralleltest
- prealloc
- predeclared
- protogetter
- scopelint
- recvcheck
- revive
- tagalign
- tagliatelle
- testpackage
- usetesting # go 1.24
- varnamelen
- whitespace
- wrapcheck
- wsl
issues:
exclude-dirs:
- internal/gen
- cmd/dev
- repos
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- internal/gen
- cmd/dev
- repos
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofumpt
exclusions:
generated: lax
paths:
- internal/gen
- cmd/dev
- repos
- third_party$
- builtin$
- examples$
+24 -77
View File
@@ -13,103 +13,96 @@
# contents of this file.
#
Aaron Bieber (qbit) <qbit@deftly.net>
Jakob Borg (calmh) <jakob@nym.se> <jakob@kastelo.net> <jborg@coreweave.com>
Audrius Butkevicius (AudriusButkevicius) <audrius.butkevicius@gmail.com> <github@audrius.rocks>
Simon Frei (imsodin) <freisim93@gmail.com>
Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com> <twilczynski@naver.com>
Alexander Graf (alex2108) <register-github@alex-graf.de>
Alexandre Viau (aviau) <alexandre@alexandreviau.net> <aviau@debian.org>
Anderson Mesquita (andersonvom) <andersonvom@gmail.com>
André Colomb (acolomb) <src@andre.colomb.de> <github.com@andre.colomb.de>
Antony Male (canton7) <antony.male@gmail.com>
Ben Schulz (uok) <ueomkail@gmail.com> <uok@users.noreply.github.com>
bt90 <btom1990@googlemail.com>
Caleb Callaway (cqcallaw) <enlightened.despot@gmail.com>
Daniel Harte (norgeous) <daniel@harte.me> <daniel@danielharte.co.uk> <norgeous@users.noreply.github.com>
Emil Lundberg <emil@emlun.se>
Eric P <eric@kastelo.net>
Evgeny Kuznetsov <evgeny@kuznetsov.md>
greatroar <61184462+greatroar@users.noreply.github.com>
Lars K.W. Gohlke (lkwg82) <lkwg82@gmx.de>
Lode Hoste (Zillode) <zillode@zillode.be>
Michael Ploujnikov (plouj) <ploujj@gmail.com>
Ross Smith II (rasa) <ross@smithii.com>
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org> <stefan@rumpelsepp.org>
Wulf Weich (wweich) <wweich@users.noreply.github.com> <wweich@gmx.de> <wulf@weich-kr.de>
Adam Piggott (ProactiveServices) <aD@simplypeachy.co.uk> <simplypeachy@users.noreply.github.com> <ProactiveServices@users.noreply.github.com> <adam@proactiveservices.co.uk>
Adel Qalieh (adelq) <aqalieh95@gmail.com> <adelq@users.noreply.github.com>
Alan Pope <alan@popey.com>
Alberto Donato <albertodonato@users.noreply.github.com>
Aleksey Vasenev <margtu-fivt@ya.ru>
Alessandro G. (alessandro.g89) <alessandro.g89@gmail.com>
Alex Ionescu <github@ionescu.sh>
Alex Lindeman <139387+aelindeman@users.noreply.github.com>
Alex Xu <alex.hello71@gmail.com>
Alexander Graf (alex2108) <register-github@alex-graf.de>
Alexander Seiler <seileralex@gmail.com>
Alexandre Alves <alexandrealvesdb.contact@gmail.com>
Alexandre Viau (aviau) <alexandre@alexandreviau.net> <aviau@debian.org>
Aman Gupta <aman@tmm1.net>
Anatoli Babenia <anatoli@rainforce.org>
Anderson Mesquita (andersonvom) <andersonvom@gmail.com>
Andreas Sommer <andreas.sommer87@googlemail.com>
andresvia <andres.via@gmail.com>
Andrew Dunham (andrew-d) <andrew@du.nham.ca>
Andrew Meyer <andrewm.bpi@gmail.com>
Andrew Rabert (nvllsvm) <ar@nullsum.net> <6550543+nvllsvm@users.noreply.github.com>
Andrey D (scienmind) <scintertech@cryptolab.net> <scienmind@users.noreply.github.com>
André Colomb (acolomb) <src@andre.colomb.de> <github.com@andre.colomb.de>
andyleap <andyleap@gmail.com>
Anjan Momi <anjan@momi.ca>
Anthony Goeckner <agoeckner@users.noreply.github.com>
Antoine Lamielle (0x010C) <antoine.lamielle@0x010c.fr> <gh@0x010c.fr>
Antony Male (canton7) <antony.male@gmail.com>
Anur <anurnomeru@163.com>
Aranjedeath <Aranjedeath@users.noreply.github.com>
Arkadiusz Tymiński <gevleeog@gmail.com>
Aroun <login@b-vo.fr>
Arthur Axel fREW Schmidt (frioux) <frew@afoolishmanifesto.com> <frioux@gmail.com>
Artur Zubilewicz <AkaZecik@users.noreply.github.com>
Audrius Butkevicius (AudriusButkevicius) <audrius.butkevicius@gmail.com> <github@audrius.rocks>
Aurélien Rainone <476650+arl@users.noreply.github.com>
BAHADIR YILMAZ <bahadiryilmaz32@gmail.com>
Bart De Vries (mogwa1) <devriesb@gmail.com>
Beat Reichenbach <44111292+beatreichenbach@users.noreply.github.com>
Ben Curthoys (bencurthoys) <ben@bencurthoys.com>
Ben Schulz (uok) <ueomkail@gmail.com> <uok@users.noreply.github.com>
Ben Shepherd (benshep) <bjashepherd@gmail.com>
Ben Sidhom (bsidhom) <bsidhom@gmail.com>
Benedikt Heine (bebehei) <bebe@bebehei.de>
Benedikt Morbach <benedikt.morbach@googlemail.com>
Benjamin Nater <17193640+bn4t@users.noreply.github.com>
Benno Fünfstück <benno.fuenfstueck@gmail.com>
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>
Brian R. Becker (brbecker) <brbecker@gmail.com>
bt90 <btom1990@googlemail.com>
Caleb Callaway (cqcallaw) <enlightened.despot@gmail.com>
Carsten Hagemann (carstenhag) <moter8@gmail.com> <carsten@chagemann.de>
Catfriend1 <16361913+Catfriend1@users.noreply.github.com>
Cathryne Linenweaver (Cathryne) <cathryne.linenweaver@gmail.com> <Cathryne@users.noreply.github.com> <katrinleinweber@MAC.local>
Cedric Staniewski (xduugu) <cedric@gmx.ca>
chenrui <rui@meetup.com>
Chih-Hsuan Yen <yan12125@gmail.com> <1937689+yan12125@users.noreply.github.com>
Choongkyu <choongkyu.kim+gh@gmail.com> <vapidlyrapid+gh@gmail.com>
Chris Howie (cdhowie) <me@chrishowie.com>
Chris Joel (cdata) <chris@scriptolo.gy>
Chris Tonkinson <chris@masterbran.ch>
Christian Kujau <ckujau@users.noreply.github.com>
Christian Prescott <me@christianprescott.com>
chucic <chucic@seznam.cz>
cjc7373 <niuchangcun@gmail.com>
Colin Kennedy (moshen) <moshen.colin@gmail.com>
Cromefire_ <tim.l@nghorst.net> <26320625+cromefire@users.noreply.github.com>
cui fliter <imcusg@gmail.com>
Cyprien Devillez <cypx@users.noreply.github.com>
d-volution <49024624+d-volution@users.noreply.github.com>
Dale Visser <dale.visser@live.com>
Dan <benda.daniel@gmail.com>
Daniel Barczyk <46358936+DanielBarczyk@users.noreply.github.com>
Daniel Bergmann (brgmnn) <dan.arne.bergmann@gmail.com> <brgmnn@users.noreply.github.com>
Daniel Harte (norgeous) <daniel@harte.me> <daniel@danielharte.co.uk> <norgeous@users.noreply.github.com>
Daniel Martí (mvdan) <mvdan@mvdan.cc>
Daniel Padrta <64928366+danpadcz@users.noreply.github.com>
Darshil Chanpura (dtchanpura) <dtchanpura@gmail.com> <dcprime314@gmail.com>
dashangcun <907225865@qq.com>
David Rimmer (dinosore) <dinosore@dbrsoftware.co.uk>
deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com>
DeflateAwning <11021263+DeflateAwning@users.noreply.github.com>
Denis A. (dva) <denisva@gmail.com>
Dennis Wilson (snnd) <dw@risu.io>
dependabot-preview[bot] <dependabot-preview[bot]@users.noreply.github.com> <27856297+dependabot-preview[bot]@users.noreply.github.com>
dependabot[bot] <dependabot[bot]@users.noreply.github.com> <49699333+dependabot[bot]@users.noreply.github.com>
derekriemer <derek.riemer@colorado.edu>
DerRockWolf <50499906+DerRockWolf@users.noreply.github.com>
desbma <desbma@users.noreply.github.com>
Devon G. Redekopp <devon@redekopp.com>
diemade <spamkill@posteo.ch>
digital <didev@dinid.net>
Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com>
Dmitry Saveliev (dsaveliev) <d.e.saveliev@gmail.com>
@@ -119,14 +112,11 @@ Dominik Heidler (asdil12) <dominik@heidler.eu>
Elias Jarlebring (jarlebring) <jarlebring@gmail.com>
Elliot Huffman <thelich2@gmail.com>
Emil Hessman (ceh) <emil@hessman.se>
Emil Lundberg <emil@emlun.se>
Eng Zer Jun <engzerjun@gmail.com>
entity0xfe <109791748+entity0xfe@users.noreply.github.com> <entity0xfe@my.domain>
Eric Lesiuta <elesiuta@gmail.com>
Eric P <eric@kastelo.net>
Erik Meitner (WSGCSysadmin) <e.meitner@willystreet.coop>
Evan Spensley <94762716+0evan@users.noreply.github.com>
Evgeny Kuznetsov <evgeny@kuznetsov.md>
Federico Castagnini (facastagnini) <federico.castagnini@gmail.com>
Felix <53702818+f-eliks@users.noreply.github.com>
Felix Ableitner (Nutomic) <me@nutomic.com>
@@ -140,7 +130,6 @@ ghjklw <malo@jaffre.info>
Gilli Sigurdsson (gillisig) <gilli@vx.is>
Gleb Sinyavskiy <zhulik.gleb@gmail.com>
Graham Miln (grahammiln) <graham.miln@dssw.co.uk> <graham.miln@miln.eu>
greatroar <61184462+greatroar@users.noreply.github.com>
Greg <gco@jazzhaiku.com>
guangwu <guoguangwu@magic-shield.com>
gudvinr <gudvinr@gmail.com>
@@ -155,50 +144,35 @@ Hugo Locurcio <hugo.locurcio@hugo.pro>
Iain Barnett <iainspeed@gmail.com>
Ian Johnson (anonymouse64) <ian.johnson@canonical.com> <person.uwsome@gmail.com>
ignacy123 <ignacy.buczek@onet.pl>
Ikko Ashimine <eltociear@gmail.com>
Ilya Brin <464157+ilyabrin@users.noreply.github.com>
Iskander Sharipov (Alex) <quasilyte@gmail.com>
Jaakko Hannikainen (jgke) <jgke@jgke.fi>
Jacek Szafarkiewicz (hadogenes) <szafar@linux.pl>
Jack Croft <jccroft1@users.noreply.github.com>
Jacob <jyundt@gmail.com>
Jake Peterson (acogdev) <jake@acogdev.com>
Jakob Borg (calmh) <jakob@nym.se> <jakob@kastelo.net> <jborg@coreweave.com>
James O'Beirne <wild-github@au92.org>
James Patterson (jpjp) <jamespatterson@operamail.com> <jpjp@users.noreply.github.com>
janost <janost@tuta.io>
Jaroslav Lichtblau <svetlemodry@users.noreply.github.com>
Jaroslav Malec (dzarda) <dzardacz@gmail.com>
jaseg <githubaccount@jaseg.net>
Jaspitta <ste.scarpitta@gmail.com>
Jauder Ho <jauderho@users.noreply.github.com>
Jaya Chithra (jayachithra) <s.k.jayachithra@gmail.com>
Jaya Kumar <jaya.kumar@ict.nl>
Jeffery To <jeffery.to@gmail.com>
jelle van der Waa <jelle@vdwaa.nl>
Jens Diemer (jedie) <github.com@jensdiemer.de> <git@jensdiemer.de>
Jerry Jacobs (xor-gate) <jerry.jacobs@xor-gate.org> <xor-gate@users.noreply.github.com>
Jesse Lucas <jesse@jesselucas.com>
Jochen Voss (seehuhn) <voss@seehuhn.de>
Johan Andersson <j@i19.se>
Johan Vromans (sciurius) <jvromans@squirrel.nl>
John Rinehart (fuzzybear3965) <johnrichardrinehart@gmail.com>
Jonas Thelemann <e-mail@jonas-thelemann.de>
Jonathan <artback@protonmail.com> <jonagn@gmail.com>
Jonathan Cross <jcross@gmail.com>
Jonta <359397+Jonta@users.noreply.github.com>
Jose Manuel Delicado (jmdaweb) <jmdaweb@hotmail.com> <jmdaweb@users.noreply.github.com>
jtagcat <git-514635f7@jtag.cat> <git-12dbd862@jtag.cat>
Julian Lehrhuber <jul13579@users.noreply.github.com>
Jörg Thalheim <Mic92@users.noreply.github.com>
Jędrzej Kula <kula.jedrek@gmail.com>
K.B.Dharun Krishna <kbdharunkrishna@gmail.com>
Kalle Laine <pahakalle@protonmail.com>
Kapil Sareen <kapilsareen584@gmail.com>
Karol Różycki (krozycki) <rozycki.karol@gmail.com>
Kebin Liu <lkebin@gmail.com>
Keith Harrison <keithh@protonmail.com>
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>
@@ -207,30 +181,23 @@ Kevin White, Jr. (kwhite17) <kevinwhite1710@gmail.com>
klemens <ka7@github.com>
Kurt Fitzner (Kudalufi) <kurt@va1der.ca> <kurt.fitzner@gmail.com>
kylosus <33132401+kylosus@users.noreply.github.com>
Lars K.W. Gohlke (lkwg82) <lkwg82@gmx.de>
Lars Lehtonen <lars.lehtonen@gmail.com>
Laurent Arnoud <laurent@spkdev.net>
Laurent Etiemble (letiemble) <laurent.etiemble@gmail.com> <laurent.etiemble@monobjc.net>
Leo Arias (elopio) <yo@elopio.net>
Liu Siyuan (liusy182) <liusy182@gmail.com> <liusy182@hotmail.com>
Lode Hoste (Zillode) <zillode@zillode.be>
Lord Landon Agahnim (LordLandon) <lordlandon@gmail.com>
LSmithx2 <42276854+lsmithx2@users.noreply.github.com>
luchenhan <168071714+luchenhan@users.noreply.github.com>
Lukas Lihotzki <lukas@lihotzki.de>
Luke Hamburg <1992842+luckman212@users.noreply.github.com>
luzpaz <luzpaz@users.noreply.github.com>
Majed Abdulaziz (majedev) <majed.alhajry@gmail.com>
Marc Laporte (marclaporte) <marc@marclaporte.com> <marc@laporte.name>
Marc Pujol (kilburn) <kilburn@la3.org>
Marcin Dziadus (marcindziadus) <dziadus.marcin@gmail.com>
marco-m <marco.molteni@laposte.net>
Marcus B Spencer <marcus@marcusspencer.xyz> <marcus@marcusspencer.us>
Marcus Legendre <marcus.legendre@gmail.com>
Mario Majila <mariustshipichik@gmail.com>
Mark Pulford (mpx) <mark@kyne.com.au>
Martchus <martchus@gmx.net>
Martin Polehla <p0l0us@users.noreply.github.com>
Mateusz Naściszewski (mateon1) <matin1111@wp.pl>
Mateusz Ż <thedead4fun@live.com>
mathias4833 <67101597+mathias4833@users.noreply.github.com>
@@ -241,15 +208,10 @@ Matteo Ruina <matteo.ruina@gmail.com>
Maurizio Tomasi <ziotom78@gmail.com>
Max <github@germancoding.com>
Max Schulze (kralo) <max.schulze@online.de> <kralo@users.noreply.github.com>
maxice8 <30738253+maxice8@users.noreply.github.com>
MaximAL <almaximal@ya.ru>
Maxime Thirouin <m@moox.io>
Maximilian <maxi.rostock@outlook.de> <public@complexvector.space>
mclang <1721600+mclang@users.noreply.github.com>
Michael Jephcote (Rewt0r) <rewt0r@gmx.com> <Rewt0r@users.noreply.github.com>
Michael Ploujnikov (plouj) <ploujj@gmail.com>
Michael Rienstra <mrienstra@gmail.com>
Michael Tilli (pyfisch) <pyfisch@gmail.com>
MichaIng <micha@dietpi.com>
Migelo <miha@filetki.si>
Mike Boone <mike@boonedocks.net>
@@ -258,7 +220,6 @@ 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>
Naveen <172697+naveensrinivasan@users.noreply.github.com>
nf <nf@wh3rd.net>
Nicholas Rishel (PrototypeNM1) <rishel.nick@gmail.com> <PrototypeNM1@users.noreply.github.com>
Nick Busey <NickBusey@users.noreply.github.com>
@@ -273,7 +234,6 @@ NoLooseEnds <jon.koslung@gmail.com>
Oliver Freyermuth <o.freyermuth@googlemail.com>
orangekame3 <miya.org.0309@gmail.com>
otbutz <tbutz@optitool.de>
Otiel <Otiel@users.noreply.github.com>
overkill <22098433+0verk1ll@users.noreply.github.com>
Oyebanji Jacob Mayowa <oyebanji05@gmail.com>
Pablo <pbaeyens31+github@gmail.com>
@@ -281,7 +241,6 @@ Pascal Jungblut (pascalj) <github@pascalj.com> <mail@pascal-jungblut.com>
Paul Brit <paulbrit44@gmail.com>
Paul Donald <newtwen+github@gmail.com>
Pawel Palenica (qepasa) <pawelpalenica11@gmail.com>
Paweł Rozlach <vespian@users.noreply.github.com>
perewa <cavalcante.ten@gmail.com>
Peter Badida <KeyWeeUsr@users.noreply.github.com>
Peter Dave Hello <hsu@peterdavehello.org>
@@ -291,19 +250,15 @@ Phani Rithvij <phanirithvij2000@gmail.com>
Phil Davis <phil.davis@inf.org>
Philippe Schommers (filoozoom) <philippe@schommers.be>
Phill Luby (pluby) <phill.luby@newredo.com>
Pier Paolo Ramon <ramonpierre@gmail.com>
Piotr Bejda (piobpl) <piotrb10@gmail.com>
polyfloyd <polyfloyd@users.noreply.github.com>
Pramodh KP (pramodhkp) <pramodh.p@directi.com> <1507241+pramodhkp@users.noreply.github.com>
Quentin Hibon <qh.public@yahoo.com>
Rahmi Pruitt <rjpruitt16@gmail.com>
red_led <red-led@users.noreply.github.com>
Richard Hartmann <RichiH@users.noreply.github.com>
Robert Carosi (nov1n) <robert@carosi.nl>
Roberto Santalla <roobre@users.noreply.github.com>
Robin Schoonover <robin@cornhooves.org>
Roman Zaynetdinov (zaynetro) <romanznet@gmail.com>
Ross Smith II (rasa) <ross@smithii.com>
rubenbe <github-com-00ff86@vandamme.email>
Ruslan Yevdokymov <38809160+ruslanye@users.noreply.github.com>
Ryan Qian <i@bitbili.net>
@@ -315,18 +270,14 @@ Sergey Mishin (ralder) <ralder@yandex.ru>
Sertonix <83883937+Sertonix@users.noreply.github.com>
Severin von Wnuck-Lipinski <ss7@live.de>
Shaarad Dalvi <60266155+shaaraddalvi@users.noreply.github.com> <shdalv@microsoft.com>
Simon Frei (imsodin) <freisim93@gmail.com>
Simon Mwepu <simonmwepu@gmail.com>
Simon Pickup <simon@pickupinfinity.com>
Sly_tom_cat <slytomcat@mail.ru>
Sonu Kumar Saw <31889738+dev-saw99@users.noreply.github.com>
Stefan Kuntz (Stefan-Code) <stefan.github@gmail.com> <Stefan.github@gmail.com>
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org> <stefan@rumpelsepp.org>
Steven Eckhoff <steven.eckhoff.opensource@gmail.com>
Suhas Gundimeda (snugghash) <suhas.gundimeda@gmail.com> <snugghash@gmail.com>
Sven Bachmann <dev@mcbachmann.de>
Syncthing Automation <automation@syncthing.net>
Syncthing Release Automation <release@syncthing.net>
Sébastien WENSKE <sebastien@wenske.fr>
Taylor Khan (nelsonkhan) <nelsonkhan@gmail.com>
Terrance <git@terrance.allofti.me>
@@ -335,14 +286,11 @@ Thomas <9749173+uhthomas@users.noreply.github.com>
Thomas Hipp <thomashipp@gmail.com>
Tim Abell (timabell) <tim@timwise.co.uk>
Tim Howes (timhowes) <timhowes@berkeley.edu>
Tim Nordenfur <tim@gurka.se>
Tobias Frölich <40638719+tobifroe@users.noreply.github.com>
Tobias Klauser <tobias.klauser@gmail.com>
Tobias Nygren (tnn2) <tnn@nygren.pp.se>
Tobias Tom (tobiastom) <t.tom@succont.de>
Tom Jakubowski <tom@crystae.net>
Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com> <twilczynski@naver.com>
Tommy Thorn <tommy-github-email@thorn.ws>
Tommy van der Vorst <tommy-github@pixelspark.nl> <tommy@pixelspark.nl>
Tully Robinson (tojrobinson) <tully@tojr.org>
Tyler Brazier (tylerbrazier) <tyler@tylerbrazier.com>
@@ -360,10 +308,9 @@ WangXi <xib1102@icloud.com>
Will Rouesnel <wrouesnel@wrouesnel.com>
William A. Kennington III (wkennington) <william@wkennington.com>
wouter bolsterlee <wouter@bolsterl.ee>
Wulf Weich (wweich) <wweich@users.noreply.github.com> <wweich@gmx.de> <wulf@weich-kr.de>
xarx00 <xarx00@users.noreply.github.com>
Xavier O. (damajor) <damajor@gmail.com>
xjtdy888 (xjtdy888) <xjtdy888@163.com>
xjtdy888 (xjtdy888) <xjtdy888@163.com> <xjtdy888@gmail.com>
Yannic A. (eipiminus1) <eipiminusone+github@gmail.com> <eipiminus1@users.noreply.github.com>
佛跳墙 <daoquan@qq.com>
落心 <luoxin.ttt@gmail.com>
+44 -20
View File
@@ -8,6 +8,7 @@ package main
import (
"bytes"
"cmp"
"context"
"crypto/tls"
"errors"
@@ -26,6 +27,7 @@ import (
"sort"
"strconv"
"syscall"
"text/tabwriter"
"time"
"github.com/alecthomas/kong"
@@ -37,6 +39,7 @@ import (
"github.com/syncthing/syncthing/cmd/syncthing/decrypt"
"github.com/syncthing/syncthing/cmd/syncthing/generate"
"github.com/syncthing/syncthing/internal/db"
"github.com/syncthing/syncthing/internal/db/sqlite"
_ "github.com/syncthing/syncthing/lib/automaxprocs"
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/config"
@@ -825,24 +828,6 @@ func exitCodeForUpgrade(err error) int {
return svcutil.ExitError.AsInt()
}
// convertLegacyArgs returns the slice of arguments with single dash long
// flags converted to double dash long flags.
func convertLegacyArgs(args []string) []string {
// Legacy args begin with a single dash, followed by two or more characters.
legacyExp := regexp.MustCompile(`^-\w{2,}`)
res := make([]string, len(args))
for i, arg := range args {
if legacyExp.MatchString(arg) {
res[i] = "-" + arg
} else {
res[i] = arg
}
}
return res
}
type versionCmd struct{}
func (versionCmd) Run() error {
@@ -900,7 +885,8 @@ func (u upgradeCmd) Run() error {
release, err := checkUpgrade()
if err == nil {
lf := flock.New(locations.Get(locations.LockFile))
locked, err := lf.TryLock()
var locked bool
locked, err = lf.TryLock()
if err != nil {
l.Warnln("Upgrade:", err)
os.Exit(1)
@@ -930,7 +916,8 @@ func (browserCmd) Run() error {
}
type debugCmd struct {
ResetDatabase resetDatabaseCmd `cmd:"" help:"Reset the database, forcing a full rescan and resync"`
ResetDatabase resetDatabaseCmd `cmd:"" help:"Reset the database, forcing a full rescan and resync"`
DatabaseStatistics databaseStatsCmd `cmd:"" help:"Display database size statistics"`
}
type resetDatabaseCmd struct{}
@@ -945,6 +932,43 @@ func (resetDatabaseCmd) Run() error {
return nil
}
type databaseStatsCmd struct{}
func (c databaseStatsCmd) Run() error {
db, err := sqlite.Open(locations.Get(locations.Database))
if err != nil {
return err
}
ds, err := db.Statistics()
if err != nil {
return err
}
tw := tabwriter.NewWriter(os.Stdout, 2, 2, 2, ' ', 0)
hdr := fmt.Sprintf("%s\t%s\t%s\t%12s\t%7s\n", "DATABASE", "FOLDER ID", "TABLE", "SIZE", "FILL")
fmt.Fprint(tw, hdr)
fmt.Fprint(tw, regexp.MustCompile(`[A-Z]`).ReplaceAllString(hdr, "="))
c.printStat(tw, ds)
return tw.Flush()
}
func (c databaseStatsCmd) printStat(w io.Writer, s *sqlite.DatabaseStatistics) {
for _, table := range s.Tables {
fmt.Fprintf(w, "%s\t%s\t%s\t%8d KiB\t%5.01f %%\n", s.Name, cmp.Or(s.FolderID, "-"), table.Name, table.Size/1024, float64(table.Size-table.Unused)*100/float64(table.Size))
}
for _, next := range s.Children {
c.printStat(w, &next)
s.Total.Size += next.Total.Size
s.Total.Unused += next.Total.Unused
}
totalName := s.Name
if len(s.Children) > 0 {
totalName += " + children"
}
fmt.Fprintf(w, "%s\t%s\t%s\t%8d KiB\t%5.01f %%\n", totalName, cmp.Or(s.FolderID, "-"), "(total)", s.Total.Size/1024, float64(s.Total.Size-s.Total.Unused)*100/float64(s.Total.Size))
}
func setConfigDataLocationsFromFlags(homeDir, confDir, dataDir string) error {
homeSet := homeDir != ""
confSet := confDir != ""
+4 -1
View File
@@ -22,7 +22,7 @@ require (
github.com/julienschmidt/httprouter v1.3.0
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/maruel/panicparse/v2 v2.5.0
github.com/mattn/go-sqlite3 v1.14.27
github.com/mattn/go-sqlite3 v1.14.28
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2
github.com/maxmind/geoipupdate/v6 v6.1.0
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
@@ -108,3 +108,6 @@ require (
// https://github.com/gobwas/glob/pull/55
replace github.com/gobwas/glob v0.2.3 => github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b
// https://github.com/mattn/go-sqlite3/pull/1338
replace github.com/mattn/go-sqlite3 v1.14.28 => github.com/calmh/go-sqlite3 v1.14.29-0.20250520105817-2e94cda3f7f8
+2 -2
View File
@@ -31,6 +31,8 @@ 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/calmh/glob v0.0.0-20220615080505-1d823af5017b h1:Fjm4GuJ+TGMgqfGHN42IQArJb77CfD/mAwLbDUoJe6g=
github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b/go.mod h1:91K7jfEsgJSyfSrX+gmrRfZMtntx6JsHolWubGXDopg=
github.com/calmh/go-sqlite3 v1.14.29-0.20250520105817-2e94cda3f7f8 h1:oNVrBJGXkD334ToEmxJz8G6LhzD1/sMA4twMHsMLzQo=
github.com/calmh/go-sqlite3 v1.14.29-0.20250520105817-2e94cda3f7f8/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/calmh/incontainer v1.0.0 h1:g2cTUtZuFGmMGX8GoykPkN1Judj2uw8/3/aEtq4Z/rg=
github.com/calmh/incontainer v1.0.0/go.mod h1:eOhqnw15c9X+4RNBe0W3HlUZFfX16O0EDsCOInTndHY=
github.com/calmh/xdr v1.2.0 h1:GaGSNH4ZDw9kNdYqle6+RcAENiaQ8/611Ok+jQbBEeU=
@@ -164,8 +166,6 @@ github.com/maruel/panicparse/v2 v2.5.0/go.mod h1:DA2fDiBk63bKfBf4CVZP9gb4fuvzdPb
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.27 h1:drZCnuvf37yPfs95E5jd9s3XhdVWLal+6BOK6qrv6IU=
github.com/mattn/go-sqlite3 v1.14.27/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2 h1:yVCLo4+ACVroOEr4iFU1iH46Ldlzz2rTuu18Ra7M8sU=
github.com/maxbrunsfeld/counterfeiter/v6 v6.11.2/go.mod h1:VzB2VoMh1Y32/QqDfg9ZJYHj99oM4LiGtqPZydTiQSQ=
github.com/maxmind/geoipupdate/v6 v6.1.0 h1:sdtTHzzQNJlXF5+fd/EoPTucRHyMonYt/Cok8xzzfqA=
+4 -2
View File
@@ -27,6 +27,7 @@
"Allowed Networks": "Разрешённые сети",
"Alphabetic": "По алфавиту",
"Altered by ignoring deletes.": "Изменено, игнорируя удаления.",
"Always turned on when the folder type is \"{%foldertype%}\".": "Всегда включено для папок с типом «{{foldertype}}».",
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Для версионирования используется внешняя программа. Ей нужно удалить файл из общей папки. Если путь к приложению содержит пробелы, его нужно взять в кавычки.",
"Anonymous Usage Reporting": "Анонимный отчет об использовании",
"Anonymous usage report format has changed. Would you like to move to the new format?": "Формат анонимных отчётов изменился. Хотите переключиться на новый формат?",
@@ -52,6 +53,7 @@
"Body:": "Тело:",
"Bugs": "Ошибки",
"Cancel": "Отмена",
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "Не может быть включено для папок с типом «{{foldertype}}».",
"Changelog": "Журнал изменений",
"Clean out after": "Очистить после",
"Cleaning Versions": "Очистка версий",
@@ -171,8 +173,8 @@
"Folder Path": "Путь к папке",
"Folder Status": "Статус папки",
"Folder Type": "Тип папки",
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Тип папки «{{receiveEncrypted}}» может быть указан только при создании новой папки.",
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Тип папки «{{receiveEncrypted}}» не может быть изменён после добавления. Вам необходимо убрать папку, удалить или дешифровать данные на диске, а затем снова добавить папку.",
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Тип папки «{{receiveEncrypted}}» может быть выбран только при добавлении новой папки.",
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Тип папки «{{receiveEncrypted}}» не может быть изменён после добавления. Вам необходимо убрать папку, удалить или дешифровать данные на диске и затем снова её добавить.",
"Folders": "Папки",
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Для следующих папок произошла ошибка при запуске отслеживания изменений. Попытки будут повторяться раз в минуту, и ошибки скоро могут быть устранены. Если этого не произойдёт, попробуйте разобраться в причинах и попросите поддержки, если у вас не получится.",
"Forever": "Вечно",
+2
View File
@@ -0,0 +1,2 @@
{
}
@@ -30,7 +30,7 @@
<h4 class="text-center" translate>The Syncthing Authors</h4>
<div class="row">
<div class="col-md-12" id="contributor-list">
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Emil Lundberg, Eric P, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ross Smith II, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, bt90, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Ionescu, Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Anatoli Babenia, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, DerRockWolf, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, Gusted, Han Boetes, HansK-p, Harrison Jones, Hazem Krimi, Heiko Zuerker, Hireworks, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, K.B.Dharun Krishna, Kalle Laine, Kapil Sareen, Karol Różycki, Kebin Liu, Keith Harrison, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Luke Hamburg, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus B Spencer, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Martin Polehla, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, Maximilian, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Paul Donald, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ruslan Yevdokymov, Ryan Qian, Sacheendra Talluri, Scott Klupfel, Sertonix, Severin von Wnuck-Lipinski, Shaarad Dalvi, Simon Mwepu, Simon Pickup, Sly_tom_cat, Sonu Kumar Saw, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Sébastien WENSKE, Taylor Khan, Terrance, TheCreeper, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tim Nordenfur, Tobias Frölich, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tommy van der Vorst, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, Vladimir Rusinov, WangXi, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, cjc7373, cui fliter, d-volution, dashangcun, derekriemer, desbma, diemade, digital, domain, entity0xfe, georgespatton, ghjklw, guangwu, gudvinr, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, kylosus, luchenhan, luzpaz, marco-m, mathias4833, maxice8, mclang, mv1005, nf, orangekame3, otbutz, overkill, perewa, polyfloyd, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
Jakob Borg, Audrius Butkevicius, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, bt90, Caleb Callaway, Daniel Harte, Emil Lundberg, Eric P, Evgeny Kuznetsov, greatroar, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Ross Smith II, Stefan Tatschner, Wulf Weich, Adam Piggott, Adel Qalieh, Aleksey Vasenev, Alessandro G., Alex Ionescu, Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Andreas Sommer, andresvia, Andrew Rabert, Andrey D, andyleap, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benno Fünfstück, Benny Ng, boomsquared, Boqin Qin, Boris Rybalkin, Brendan Long, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Christian Kujau, Christian Prescott, chucic, cjc7373, Colin Kennedy, Cromefire_, Cyprien Devillez, d-volution, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, dashangcun, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, derekriemer, DerRockWolf, desbma, Devon G. Redekopp, digital, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, domain, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Eng Zer Jun, entity0xfe, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, georgespatton, ghjklw, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, guangwu, gudvinr, Gusted, Han Boetes, HansK-p, Harrison Jones, Hazem Krimi, Heiko Zuerker, Hireworks, Hugo Locurcio, Iain Barnett, Ian Johnson, ignacy123, Iskander Sharipov, Jaakko Hannikainen, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jaya Chithra, Jaya Kumar, Jeffery To, jelle van der Waa, Jens Diemer, Jochen Voss, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jose Manuel Delicado, jtagcat, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, Kapil Sareen, Karol Różycki, Kebin Liu, Keith Harrison, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., klemens, Kurt Fitzner, kylosus, Lars Lehtonen, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, LSmithx2, Lukas Lihotzki, Luke Hamburg, luzpaz, Majed Abdulaziz, Marc Laporte, Marcin Dziadus, Marcus B Spencer, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Mateusz Naściszewski, Mateusz Ż, mathias4833, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maximilian, Michael Jephcote, Michael Rienstra, MichaIng, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, mv1005, Nate Morrison, nf, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, orangekame3, otbutz, overkill, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Paul Donald, Pawel Palenica, perewa, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Philippe Schommers, Phill Luby, Piotr Bejda, polyfloyd, Quentin Hibon, Rahmi Pruitt, red_led, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, rubenbe, Ruslan Yevdokymov, Ryan Qian, Ryan Sullivan, Sacheendra Talluri, Scott Klupfel, sec65, Sergey Mishin, Sertonix, Severin von Wnuck-Lipinski, Shaarad Dalvi, Simon Mwepu, Simon Pickup, Sly_tom_cat, Sonu Kumar Saw, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Sébastien WENSKE, Taylor Khan, Terrance, TheCreeper, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tobias Frölich, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy van der Vorst, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, vapatel2, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, villekalliomaki, Vladimir Rusinov, wangguoliang, WangXi, Will Rouesnel, William A. Kennington III, wouter bolsterlee, xarx00, Xavier O., xjtdy888, Yannic A., 佛跳墙, 落心
</div>
</div>
</div>
+69
View File
@@ -0,0 +1,69 @@
// Copyright (C) 2025 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 sqlite
type DatabaseStatistics struct {
Name string `json:"name"`
FolderID string `json:"folderID,omitempty"`
Tables []TableStatistics `json:"tables"`
Total TableStatistics `json:"total"`
Children []DatabaseStatistics `json:"children,omitempty"`
}
type TableStatistics struct {
Name string `json:"name,omitempty"`
Size int64 `json:"size"`
Unused int64 `json:"unused"`
}
func (s *DB) Statistics() (*DatabaseStatistics, error) {
ts, total, err := s.tableStats()
if err != nil {
return nil, wrap(err)
}
ds := DatabaseStatistics{
Name: s.baseName,
Tables: ts,
Total: total,
}
err = s.forEachFolder(func(fdb *folderDB) error {
tables, total, err := fdb.tableStats()
if err != nil {
return wrap(err)
}
ds.Children = append(ds.Children, DatabaseStatistics{
Name: fdb.baseName,
FolderID: fdb.folderID,
Tables: tables,
Total: total,
})
return nil
})
if err != nil {
return nil, wrap(err)
}
return &ds, nil
}
func (s *baseDB) tableStats() ([]TableStatistics, TableStatistics, error) {
var stats []TableStatistics
if err := s.stmt(`
SELECT name, pgsize AS size, unused FROM dbstat
WHERE aggregate=true
ORDER BY name
`).Select(&stats); err != nil {
return nil, TableStatistics{}, wrap(err)
}
var total TableStatistics
for _, s := range stats {
total.Size += s.Size
total.Unused += s.Unused
}
return stats, total, nil
}
+1
View File
@@ -48,6 +48,7 @@ var (
}
replaceTags = map[string]string{
"sqlite_omit_load_extension": "",
"sqlite_dbstat": "",
"osusergo": "",
"netgo": "",
}
+4
View File
@@ -235,6 +235,10 @@ func ReadJSON(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
func (cfg Configuration) Copy() Configuration {
newCfg := cfg
// Deep copy Defaults
newCfg.Defaults.Folder = cfg.Defaults.Folder.Copy()
newCfg.Defaults.Device = cfg.Defaults.Device.Copy()
// Deep copy FolderConfigurations
newCfg.Folders = make([]FolderConfiguration, len(cfg.Folders))
for i := range newCfg.Folders {
+2 -2
View File
@@ -67,8 +67,8 @@ type OptionsConfiguration struct {
AnnounceLANAddresses bool `json:"announceLANAddresses" xml:"announceLANAddresses" default:"true"`
SendFullIndexOnUpgrade bool `json:"sendFullIndexOnUpgrade" xml:"sendFullIndexOnUpgrade"`
FeatureFlags []string `json:"featureFlags" xml:"featureFlag"`
AuditEnabled bool `json:"auditEnabled" xml:"auditEnabled" default:"false"`
AuditFile string `json:"auditFile" xml:"auditFile"`
AuditEnabled bool `json:"auditEnabled" xml:"auditEnabled" default:"false" restart:"true"`
AuditFile string `json:"auditFile" xml:"auditFile" restart:"true"`
// The number of connections at which we stop trying to connect to more
// devices, zero meaning no limit. Does not affect incoming connections.
ConnectionLimitEnough int `json:"connectionLimitEnough" xml:"connectionLimitEnough"`
+7 -8
View File
@@ -1286,11 +1286,6 @@ func (f *sendReceiveFolder) shortcutFile(file protocol.FileInfo, dbUpdateChan ch
// copierRoutine reads copierStates until the in channel closes and performs
// the relevant copies when possible, or passes it to the puller routine.
func (f *sendReceiveFolder) copierRoutine(in <-chan copyBlocksState, pullChan chan<- pullBlockState, out chan<- *sharedPullerState) {
buf := protocol.BufferPool.Get(protocol.MinBlockSize)
defer func() {
protocol.BufferPool.Put(buf)
}()
otherFolderFilesystems := make(map[string]fs.Filesystem)
for folder, cfg := range f.model.cfg.Folders() {
if folder == f.ID {
@@ -1333,7 +1328,7 @@ func (f *sendReceiveFolder) copierRoutine(in <-chan copyBlocksState, pullChan ch
continue
}
if f.copyBlock(block, state, otherFolderFilesystems, buf) {
if f.copyBlock(block, state, otherFolderFilesystems) {
state.copyDone(block)
continue
}
@@ -1362,8 +1357,9 @@ func (f *sendReceiveFolder) copierRoutine(in <-chan copyBlocksState, pullChan ch
}
// Returns true when the block was successfully copied.
func (f *sendReceiveFolder) copyBlock(block protocol.BlockInfo, state copyBlocksState, otherFolderFilesystems map[string]fs.Filesystem, buf []byte) bool {
buf = protocol.BufferPool.Upgrade(buf, int(block.Size))
func (f *sendReceiveFolder) copyBlock(block protocol.BlockInfo, state copyBlocksState, otherFolderFilesystems map[string]fs.Filesystem) bool {
buf := protocol.BufferPool.Get(int(block.Size))
defer protocol.BufferPool.Put(buf)
// Hope that it's usually in the same folder, so start with that
// one. Also possibly more efficient copy (same filesystem).
@@ -1978,6 +1974,9 @@ func (f *sendReceiveFolder) deleteDirOnDiskHandleChildren(dir string, scanChan c
return nil
}
cf, ok, err := f.model.sdb.GetDeviceFile(f.folderID, protocol.LocalDeviceID, path)
if err != nil {
return err
}
switch {
case !ok || cf.IsDeleted():
// Something appeared in the dir that we either are not
+2 -1
View File
@@ -194,7 +194,8 @@ func (s *indexHandler) Serve(ctx context.Context) (err error) {
// currently in the database, wait for the local index to update. The
// local index may update for other folders than the one we are
// sending for.
seq, err := s.sdb.GetDeviceSequence(s.folder, protocol.LocalDeviceID)
var seq int64
seq, err = s.sdb.GetDeviceSequence(s.folder, protocol.LocalDeviceID)
if err != nil {
return err
}
+1 -15
View File
@@ -59,7 +59,7 @@ func (p *bufferPool) Get(size int) []byte {
}
// Put makes the given byte slice available again in the global pool.
// You must only Put() slices that were returned by Get() or Upgrade().
// You must only Put() slices that were returned by Get().
func (p *bufferPool) Put(bs []byte) {
// Don't buffer slices outside of our pool range
if cap(bs) > MaxBlockSize || cap(bs) < MinBlockSize {
@@ -72,20 +72,6 @@ func (p *bufferPool) Put(bs []byte) {
p.pools[bkt].Put(&bs)
}
// Upgrade grows the buffer to the requested size, while attempting to reuse
// it if possible.
func (p *bufferPool) Upgrade(bs []byte, size int) []byte {
if cap(bs) >= size {
// Reslicing is enough, lets go!
return bs[:size]
}
// It was too small. But it pack into the pool and try to get another
// buffer.
p.Put(bs)
return p.Get(size)
}
// getBucketForLen returns the bucket where we should get a slice of a
// certain length. Each bucket is guaranteed to hold slices that are
// precisely the block size for that bucket, so if the block size is larger
+5 -8
View File
@@ -512,8 +512,9 @@ func (c *rawConnection) readMessageAfterHeader(hdr *bep.Header, fourByteBuf []by
// Then comes the message
buf := BufferPool.Get(int(msgLen))
defer BufferPool.Put(buf)
if _, err := io.ReadFull(c.cr, buf); err != nil {
BufferPool.Put(buf)
return nil, fmt.Errorf("reading message: %w", err)
}
@@ -525,7 +526,6 @@ func (c *rawConnection) readMessageAfterHeader(hdr *bep.Header, fourByteBuf []by
case bep.MessageCompression_MESSAGE_COMPRESSION_LZ4:
decomp, err := lz4Decompress(buf)
BufferPool.Put(buf)
if err != nil {
return nil, fmt.Errorf("decompressing message: %w", err)
}
@@ -541,14 +541,11 @@ func (c *rawConnection) readMessageAfterHeader(hdr *bep.Header, fourByteBuf []by
msg, err := newMessage(hdr.Type)
if err != nil {
BufferPool.Put(buf)
return nil, err
}
if err := proto.Unmarshal(buf, msg); err != nil {
BufferPool.Put(buf)
return nil, fmt.Errorf("unmarshalling message: %w", err)
}
BufferPool.Put(buf)
return msg, nil
}
@@ -567,16 +564,16 @@ func (c *rawConnection) readHeader(fourByteBuf []byte) (*bep.Header, error) {
// Then comes the header
buf := BufferPool.Get(int(hdrLen))
defer BufferPool.Put(buf)
if _, err := io.ReadFull(c.cr, buf); err != nil {
BufferPool.Put(buf)
return nil, fmt.Errorf("reading header: %w", err)
}
var hdr bep.Header
err := proto.Unmarshal(buf, &hdr)
BufferPool.Put(buf)
if err != nil {
return nil, fmt.Errorf("unmarshalling header: %w %x", err, buf)
return nil, fmt.Errorf("unmarshalling header: %w", err)
}
metricDeviceRecvDecompressedBytes.WithLabelValues(c.idString).Add(float64(2 + len(buf)))
+2 -3
View File
@@ -16,7 +16,6 @@ import (
"time"
"github.com/syncthing/syncthing/internal/db"
newdb "github.com/syncthing/syncthing/internal/db"
"github.com/syncthing/syncthing/internal/db/olddb"
"github.com/syncthing/syncthing/internal/db/olddb/backend"
"github.com/syncthing/syncthing/internal/db/sqlite"
@@ -146,13 +145,13 @@ func copyFile(src, dst string) error {
}
// Opens a database
func OpenDatabase(path string, deleteRetention time.Duration) (newdb.DB, error) {
func OpenDatabase(path string, deleteRetention time.Duration) (db.DB, error) {
sql, err := sqlite.Open(path, sqlite.WithDeleteRetention(deleteRetention))
if err != nil {
return nil, err
}
sdb := newdb.MetricsWrap(sql)
sdb := db.MetricsWrap(sql)
return sdb, nil
}
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "STDISCOSRV" "1" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "STDISCOSRV" "1" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
stdiscosrv \- Syncthing Discovery Server
.SH SYNOPSIS
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "STRELAYSRV" "1" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "STRELAYSRV" "1" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
strelaysrv \- Syncthing Relay Server
.SH SYNOPSIS
+4 -85
View File
@@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-BEP" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-BEP" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-bep \- Block Exchange Protocol v1
.SH INTRODUCTION AND DEFINITIONS
@@ -61,7 +61,7 @@ level protocols providing encryption and authentication.
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
| Block Exchange Protocol |
|\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-|
| Encryption & Auth (TLS 1.2) |
| Encryption & Auth (TLS 1.3) |
|\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-|
| Reliable Transport |
|\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-|
@@ -70,13 +70,8 @@ v ... v
.UNINDENT
.UNINDENT
.sp
The encryption and authentication layer SHALL use TLS 1.2 or a higher
revision. A strong cipher suite SHALL be used, with “strong cipher
suite” being defined as being without known weaknesses and providing
Perfect Forward Secrecy (PFS). Examples of strong cipher suites are
given at the end of this document. This is not to be taken as an
exhaustive list of allowed cipher suites but represents best practices
at the time of writing.
The encryption and authentication layer SHALL use TLS 1.3 or a higher
revision.
.sp
The exact nature of the authentication is up to the application, however
it SHALL be based on the TLS certificate presented at the start of the
@@ -1054,82 +1049,6 @@ retrieves the data from the folder and transmits Response records (9 through
message (13). Both peers enter idle state after 13. At some later time 14,
the ping timer on device B expires and a Ping message is sent. The same
process occurs for device A at 15.
.SH EXAMPLES OF STRONG CIPHER SUITES
.TS
box center;
l|l|l.
T{
ID
T} T{
Name
T} T{
Description
T}
_
T{
0x009F
T} T{
DHE\-RSA\-AES256\-GCM\-SHA384
T} T{
TLSv1.2 DH RSA AESGCM(256) AEAD
T}
_
T{
0x006B
T} T{
DHE\-RSA\-AES256\-SHA256
T} T{
TLSv1.2 DH RSA AES(256) SHA256
T}
_
T{
0xC030
T} T{
ECDHE\-RSA\-AES256\-GCM\-SHA384
T} T{
TLSv1.2 ECDH RSA AESGCM(256) AEAD
T}
_
T{
0xC028
T} T{
ECDHE\-RSA\-AES256\-SHA384
T} T{
TLSv1.2 ECDH RSA AES(256) SHA384
T}
_
T{
0x009E
T} T{
DHE\-RSA\-AES128\-GCM\-SHA256
T} T{
TLSv1.2 DH RSA AESGCM(128) AEAD
T}
_
T{
0x0067
T} T{
DHE\-RSA\-AES128\-SHA256
T} T{
TLSv1.2 DH RSA AES(128) SHA256
T}
_
T{
0xC02F
T} T{
ECDHE\-RSA\-AES128\-GCM\-SHA256
T} T{
TLSv1.2 ECDH RSA AESGCM(128) AEAD
T}
_
T{
0xC027
T} T{
ECDHE\-RSA\-AES128\-SHA256
T} T{
TLSv1.2 ECDH RSA AES(128) SHA256
T}
.TE
.SH AUTHOR
The Syncthing Authors
.SH COPYRIGHT
+6 -5
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-CONFIG" "5" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-CONFIG" "5" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-config \- Syncthing Configuration
.SH SYNOPSIS
@@ -567,8 +567,8 @@ change this unless you know what youre doing.
.TP
.B maxConflicts
The maximum number of conflict copies to keep around for any given file.
The default, \fB\-1\fP, means an unlimited number. Setting this to \fB0\fP disables
conflict copies altogether.
The default is \fB10\fP\&. \fB\-1\fP, means an unlimited number.
Setting this to \fB0\fP disables conflict copies altogether.
.UNINDENT
.INDENT 0.0
.TP
@@ -1432,8 +1432,9 @@ ECN bits into account.
.INDENT 0.0
.TP
.B stunServer
Server to be used for STUN, given as ip:port. The keyword \fBdefault\fP gets
expanded to a set of public STUN servers.
Server to use for STUN, given as ip:port. The keyword \fBdefault\fP gets
expanded to a set of public STUN servers, with preference given to those
hosted by the Syncthing project.
.sp
To configure multiple servers, you can either: repeat \fB<stunServer>\fP tags
in the configuration file or enter several servers separated by commas in
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-DEVICE-IDS" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-DEVICE-IDS" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-device-ids \- Understanding Device IDs
.sp
+28 -5
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-EVENT-API" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-EVENT-API" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-event-api \- Event API
.SH DESCRIPTION
@@ -845,9 +845,7 @@ Deprecated since version v1.10.0: The \fBversion\fP field is a legacy name kept
.sp
When authentication is enabled for the GUI, this event is emitted on every
login attempt. If either the username or password are incorrect, \fBsuccess\fP
is false and in any case the given username is returned. The included
remote address concerns the immediate connecting host, which may not be the
origin of the request, but e.g. a reverse proxy.
is false and in any case the given username is returned.
.INDENT 0.0
.INDENT 3.5
.sp
@@ -856,7 +854,32 @@ origin of the request, but e.g. a reverse proxy.
\(dqid\(dq : 187,
\(dqtime\(dq : \(dq2017\-03\-07T00:19:24.420386143+01:00\(dq,
\(dqdata\(dq : {
\(dqremoteAddress\(dq : \(dq127.0.0.1:55530\(dq,
\(dqremoteAddress\(dq : \(dq127.0.0.1\(dq,
\(dqusername\(dq : \(dqsomename\(dq,
\(dqsuccess\(dq : false
},
\(dqtype\(dq : \(dqLoginAttempt\(dq,
\(dqglobalID\(dq : 195
}
.EE
.UNINDENT
.UNINDENT
.sp
If the \fBX\-Forwared\-For\fP header is present and the connecting host is
either on \fBlocalhost\fP or on the same LAN, it will be treated as a reverse
proxy. In this case, the \fBremoteAddress\fP field is filled with the leftmost
IP address from the header, and the additional \fBproxy\fP field retains the
original IP of the connecting host.
.INDENT 0.0
.INDENT 3.5
.sp
.EX
{
\(dqid\(dq : 187,
\(dqtime\(dq : \(dq2017\-03\-07T00:19:24.420386143+01:00\(dq,
\(dqdata\(dq : {
\(dqproxy\(dq : \(dq127.0.0.1\(dq,
\(dqremoteAddress\(dq : \(dq192.168.178.10\(dq,
\(dqusername\(dq : \(dqsomename\(dq,
\(dqsuccess\(dq : false
},
+11 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-FAQ" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-FAQ" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-faq \- Frequently Asked Questions
.INDENT 0.0
@@ -158,6 +158,16 @@ Extended attributes (when enabled)
POSIX or NFS ACLs (as part of extended attributes)
.UNINDENT
.sp
\fBNOTE:\fP
.INDENT 0.0
.INDENT 3.5
Note that what can be synced often depends on the operating system, file
system, and possibly other factors. For example, even though Syncthing may
try to synchronise symbolic links on Android, this will not succeed, as the
OS does not support them on the user storage.
.UNINDENT
.UNINDENT
.sp
The following are \fInot\fP synchronized;
.INDENT 0.0
.IP \(bu 2
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-GLOBALDISCO" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-GLOBALDISCO" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-globaldisco \- Global Discovery Protocol v3
.SH ANNOUNCEMENTS
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-LOCALDISCO" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-LOCALDISCO" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-localdisco \- Local Discovery Protocol v4
.SH MODE OF OPERATION
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-NETWORKING" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-NETWORKING" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-networking \- Firewall Setup
.SH ROUTER SETUP
+1 -1
View File
@@ -28,7 +28,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-RELAY" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-RELAY" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-relay \- Relay Protocol v1
.SH WHAT IS A RELAY?
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-REST-API" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-REST-API" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-rest-api \- REST API
.sp
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-SECURITY" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-SECURITY" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-security \- Security Principles
.sp
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-STIGNORE" "5" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-STIGNORE" "5" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-stignore \- Prevent files from being synchronized to other nodes
.SH SYNOPSIS
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-VERSIONING" "7" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING-VERSIONING" "7" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing-versioning \- Keep automatic backups of deleted files by other nodes
.sp
+1 -1
View File
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING" "1" "May 01, 2025" "v1.29.3" "Syncthing"
.TH "SYNCTHING" "1" "May 15, 2025" "v1.29.6" "Syncthing"
.SH NAME
syncthing \- Syncthing
.SH SYNOPSIS
+158 -171
View File
@@ -14,14 +14,14 @@ package main
import (
"bytes"
"cmp"
"fmt"
"io"
"log"
"math"
"os"
"os/exec"
"regexp"
"sort"
"slices"
"strings"
)
@@ -64,59 +64,33 @@ type author struct {
func main() {
// Read authors from the AUTHORS file
authors := getAuthors()
// Grab the set of thus known email addresses
listed := make(stringSet)
names := make(map[string]int)
for i, a := range authors {
names[a.name] = i
for _, e := range a.emails {
listed.add(e)
}
}
authorSet := getAuthors()
// Grab the set of all known authors based on the git log, and add any
// missing ones to the authors list.
all := allAuthors()
for email, name := range all {
if listed.has(email) {
continue
}
addAuthors(authorSet)
if _, ok := names[name]; ok && name != "" {
// We found a match on name
authors[names[name]].emails = append(authors[names[name]].emails, email)
listed.add(email)
continue
}
authors := authorSet.filteredAuthors()
authors = append(authors, author{
name: name,
emails: []string{email},
})
names[name] = len(authors) - 1
listed.add(email)
}
// Write authors to the about dialog
// Write author names in GUI about modal
getContributions(authors)
sort.Sort(byContributions(authors))
slices.SortFunc(authors, func(a, b author) int {
return cmp.Or(
-cmp.Compare(a.log10commits, b.log10commits),
cmp.Compare(strings.ToLower(a.name), strings.ToLower(b.name)))
})
var lines []string
for _, author := range authors {
if authorBotsRe.MatchString(author.name) {
// Only humans are eligible, pending future legislation to the
// contrary.
continue
}
lines = append(lines, author.name)
}
replacement := strings.Join(lines, ", ")
authorsRe := regexp.MustCompile(`(?s)id="contributor-list">.*?</div>`)
bs := readAll(htmlFile)
bs, err := os.ReadFile(htmlFile)
if err != nil {
log.Fatal(err)
}
bs = authorsRe.ReplaceAll(bs, []byte("id=\"contributor-list\">\n"+replacement+"\n </div>"))
if err := os.WriteFile(htmlFile, bs, 0o644); err != nil {
@@ -125,8 +99,6 @@ func main() {
// Write AUTHORS file
sort.Sort(byName(authors))
out, err := os.Create("AUTHORS")
if err != nil {
log.Fatal(err)
@@ -141,16 +113,22 @@ func main() {
for _, email := range author.emails {
fmt.Fprintf(out, " <%s>", email)
}
fmt.Fprintf(out, "\n")
fmt.Fprint(out, "\n")
}
out.Close()
}
func getAuthors() []author {
bs := readAll("AUTHORS")
lines := strings.Split(string(bs), "\n")
var authors []author
func getAuthors() *authorSet {
bs, err := os.ReadFile("AUTHORS")
if err != nil {
log.Fatal(err)
}
lines := strings.Split(string(bs), "\n")
authors := &authorSet{
emails: make(map[string]int),
commits: make(map[string]stringSet),
}
for _, line := range lines {
if len(line) == 0 || line[0] == '#' {
continue
@@ -159,7 +137,9 @@ func getAuthors() []author {
fields := strings.Fields(line)
var author author
for _, field := range fields {
if m := nicknameRe.FindStringSubmatch(field); len(m) > 1 {
if field == "#" {
break
} else if m := nicknameRe.FindStringSubmatch(field); len(m) > 1 {
author.nickname = m[1]
} else if m := emailRe.FindStringSubmatch(field); len(m) > 1 {
author.emails = append(author.emails, m[1])
@@ -172,53 +152,11 @@ func getAuthors() []author {
}
}
authors = append(authors, author)
authors.add(author)
}
return authors
}
func readAll(path string) []byte {
fd, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
defer fd.Close()
bs, err := io.ReadAll(fd)
if err != nil {
log.Fatal(err)
}
return bs
}
// Add number of commits per author to the author list.
func getContributions(authors []author) {
buf := new(bytes.Buffer)
cmd := exec.Command("git", "log", "--pretty=format:%ae")
cmd.Stdout = buf
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
next:
for _, line := range strings.Split(buf.String(), "\n") {
for i := range authors {
for _, email := range authors[i].emails {
if email == line {
authors[i].commits++
continue next
}
}
}
}
for i := range authors {
authors[i].log10commits = int(math.Log10(float64(authors[i].commits + 1)))
}
}
// list of commits that we don't include in our author file; because they
// are legacy things that don't affect code, are committed with incorrect
// address, or for other reasons.
@@ -230,102 +168,95 @@ var excludeCommits = stringSetFromStrings([]string{
"9bdcadf6345aba3a939e9e58d85b89dbe9d44bc9",
"b933e9666abdfcd22919dd458c930d944e1e1b7f",
"b84d960a81c1282a79e2b9477558de4f1af6faae",
"4dfb9d7c83ed172f12ae19408517961f4a49beeb",
})
// allAuthors returns the set of authors in the git commit log, except those
// in excluded commits.
func allAuthors() map[string]string {
// Format is hash, email, name, newline, body. The body is indented with
// one space, to differentiate from the hash lines.
args := append([]string{"log", "--format=%H %ae %an%n%w(,1,1)%b"})
cmd := exec.Command("git", args...)
bs, err := cmd.Output()
func addAuthors(authors *authorSet) {
// All existing source-tracked files
bs, err := exec.Command("git", "ls-tree", "-r", "HEAD", "--name-only").CombinedOutput()
if err != nil {
log.Fatal("git:", err)
fmt.Println(string(bs))
log.Fatal("git ls-tree:", err)
}
files := strings.Split(string(bs), "\n")
files = slices.DeleteFunc(files, func(s string) bool {
return !(strings.HasPrefix(s, "assets/") ||
strings.HasPrefix(s, "cmd/") ||
strings.HasPrefix(s, "etc/") ||
strings.HasPrefix(s, "gui/") ||
strings.HasPrefix(s, "internal/") ||
strings.HasPrefix(s, "lib/") ||
strings.HasPrefix(s, "proto/") ||
strings.HasPrefix(s, "script/") ||
strings.HasPrefix(s, "test/") ||
strings.HasPrefix(s, "Dockerfile") ||
s == "build.go")
})
coAuthoredPrefix := "Co-authored-by: "
names := make(map[string]string)
skipCommit := false
for _, line := range bytes.Split(bs, []byte{'\n'}) {
if len(line) == 0 {
continue
for _, file := range files {
// All commits affecting those files, following any renames to their
// origin. Format is hash, email, name, newline, body. The body is
// indented with one space, to differentiate from the hash lines.
args := []string{"log", "--format=%H %ae %an%n%w(,1,1)%b", "--follow", "--", file}
bs, err = exec.Command("git", args...).CombinedOutput()
if err != nil {
fmt.Println(string(bs))
log.Fatal("git log:", err)
}
switch line[0] {
case ' ':
// Look for Co-authored-by: lines in the commit body.
if skipCommit {
skipCommit := false
var hash, email, name string
for _, line := range bytes.Split(bs, []byte{'\n'}) {
if len(line) == 0 {
continue
}
line = line[1:]
if bytes.HasPrefix(line, []byte(coAuthoredPrefix)) {
// Co-authored-by: Name Name <email@example.com>
line = line[len(coAuthoredPrefix):]
if name, email, ok := strings.Cut(string(line), "<"); ok {
name = strings.TrimSpace(name)
email = strings.Trim(strings.TrimSpace(email), "<>")
if email == "@" {
// GitHub special for users who hide their email.
continue
}
if names[email] == "" {
names[email] = name
switch line[0] {
case ' ':
// Look for Co-authored-by: lines in the commit body.
if skipCommit {
continue
}
line = line[1:]
if bytes.HasPrefix(line, []byte(coAuthoredPrefix)) {
// Co-authored-by: Name Name <email@example.com>
line = line[len(coAuthoredPrefix):]
if name, email, ok := strings.Cut(string(line), "<"); ok {
name = strings.TrimSpace(name)
email = strings.Trim(strings.TrimSpace(email), "<>")
if email == "@" {
// GitHub special for users who hide their email.
continue
}
authors.setName(email, name)
authors.addCommit(email, hash)
}
}
}
default: // hash email name
fields := strings.SplitN(string(line), " ", 3)
if len(fields) != 3 {
continue
}
hash, email, name := fields[0], fields[1], fields[2]
default: // hash email name
fields := strings.SplitN(string(line), " ", 3)
if len(fields) != 3 {
continue
}
hash, email, name = fields[0], fields[1], fields[2]
if excludeCommits.has(hash) {
skipCommit = true
continue
}
skipCommit = false
if excludeCommits.has(hash) {
skipCommit = true
continue
}
skipCommit = false
if names[email] == "" {
names[email] = name
authors.setName(email, name)
authors.addCommit(email, hash)
}
}
}
return names
}
type byContributions []author
func (l byContributions) Len() int { return len(l) }
// Sort first by log10(commits), then by name. This means that we first get
// an alphabetic list of people with >= 1000 commits, then a list of people
// with >= 100 commits, and so on.
func (l byContributions) Less(a, b int) bool {
if l[a].log10commits != l[b].log10commits {
return l[a].log10commits > l[b].log10commits
}
return l[a].name < l[b].name
}
func (l byContributions) Swap(a, b int) { l[a], l[b] = l[b], l[a] }
type byName []author
func (l byName) Len() int { return len(l) }
func (l byName) Less(a, b int) bool {
aname := strings.ToLower(l[a].name)
bname := strings.ToLower(l[b].name)
return aname < bname
}
func (l byName) Swap(a, b int) { l[a], l[b] = l[b], l[a] }
// A simple string set type
type stringSet map[string]struct{}
@@ -347,12 +278,68 @@ func (s stringSet) has(e string) bool {
return ok
}
func (s stringSet) except(other stringSet) stringSet {
diff := make(stringSet)
for e := range s {
if !other.has(e) {
diff.add(e)
// A set of authors
type authorSet struct {
authors []author
emails map[string]int // email to author index
commits map[string]stringSet // email to commit hashes
}
func (a *authorSet) add(author author) {
for _, e := range author.emails {
if idx, ok := a.emails[e]; ok {
emails := append(author.emails, a.authors[idx].emails...)
slices.Sort(emails)
emails = slices.Compact(emails)
a.authors[idx].name = author.name
a.authors[idx].emails = emails
for _, e := range emails {
a.emails[e] = idx
}
return
}
}
return diff
for _, e := range author.emails {
a.emails[e] = len(a.authors)
}
a.authors = append(a.authors, author)
}
func (a *authorSet) setName(email, name string) {
idx, ok := a.emails[email]
if !ok {
a.emails[email] = len(a.authors)
a.authors = append(a.authors, author{name: name, emails: []string{email}})
} else if a.authors[idx].name == "" {
a.authors[idx].name = name
}
}
func (a *authorSet) addCommit(email, hash string) {
ss, ok := a.commits[email]
if !ok {
ss = make(stringSet)
a.commits[email] = ss
}
ss.add(hash)
}
func (a *authorSet) filteredAuthors() []author {
authors := make([]author, len(a.authors))
copy(authors, a.authors)
for i, author := range authors {
for _, e := range author.emails {
authors[i].commits += len(a.commits[e])
}
}
authors = slices.DeleteFunc(authors, func(a author) bool {
return a.commits == 0 || authorBotsRe.MatchString(a.name)
})
for i := range authors {
authors[i].log10commits = int(math.Log10(float64(authors[i].commits)))
}
return authors
}