From ddd98a818a831d789a7b26ef5275407212e31097 Mon Sep 17 00:00:00 2001 From: Syncthing Release Automation Date: Mon, 26 May 2025 03:55:20 +0000 Subject: [PATCH 1/5] chore(gui, man, authors): update docs, translations, and contributors --- AUTHORS | 2 ++ gui/default/assets/lang/lang-ar.json | 4 ++- gui/default/assets/lang/lang-ro-RO.json | 1 + gui/default/assets/lang/lang-sr.json | 34 +++++++++++++++++++ .../syncthing/core/aboutModalView.html | 2 +- man/stdiscosrv.1 | 2 +- man/strelaysrv.1 | 2 +- man/syncthing-bep.7 | 2 +- man/syncthing-config.5 | 2 +- man/syncthing-device-ids.7 | 2 +- man/syncthing-event-api.7 | 2 +- man/syncthing-faq.7 | 2 +- man/syncthing-globaldisco.7 | 2 +- man/syncthing-localdisco.7 | 2 +- man/syncthing-networking.7 | 2 +- man/syncthing-relay.7 | 2 +- man/syncthing-rest-api.7 | 2 +- man/syncthing-security.7 | 2 +- man/syncthing-stignore.5 | 2 +- man/syncthing-versioning.7 | 2 +- man/syncthing.1 | 2 +- 21 files changed, 57 insertions(+), 18 deletions(-) diff --git a/AUTHORS b/AUTHORS index bda3bb73c..af364249c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -48,6 +48,7 @@ Arkadiusz Tymiński Aroun Arthur Axel fREW Schmidt (frioux) Artur Zubilewicz +Ashish Bhate Audrius Butkevicius (AudriusButkevicius) Aurélien Rainone <476650+arl@users.noreply.github.com> BAHADIR YILMAZ @@ -295,6 +296,7 @@ Pier Paolo Ramon Piotr Bejda (piobpl) polyfloyd Pramodh KP (pramodhkp) <1507241+pramodhkp@users.noreply.github.com> +pullmerge <166967364+pullmerge@users.noreply.github.com> Quentin Hibon Rahmi Pruitt red_led diff --git a/gui/default/assets/lang/lang-ar.json b/gui/default/assets/lang/lang-ar.json index 5d7dbd1db..83bee76e7 100644 --- a/gui/default/assets/lang/lang-ar.json +++ b/gui/default/assets/lang/lang-ar.json @@ -2,7 +2,7 @@ "A device with that ID is already added.": "أضيف هذا الجهاز بالفعل.", "A negative number of days doesn't make sense.": "لا يمكن استخدام قيمة سالبة لعدد الأيام.", "A new major version may not be compatible with previous versions.": "الإصدار الجديد قد لا يتوافق مع الإصدارات السابقة.", - "API Key": "مفتاح API", + "API Key": "مفتاح واجهة برمجة التطبيقات \"API\"", "About": "حول", "Action": "إجراء", "Actions": "الإجراءات", @@ -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": "إصدارات نظيفة", diff --git a/gui/default/assets/lang/lang-ro-RO.json b/gui/default/assets/lang/lang-ro-RO.json index 9ed7d2eb4..7af97f17f 100644 --- a/gui/default/assets/lang/lang-ro-RO.json +++ b/gui/default/assets/lang/lang-ro-RO.json @@ -26,6 +26,7 @@ "Allow Anonymous Usage Reporting?": "Permiteţi raportarea anonimă de folosire a aplicaţiei?", "Allowed Networks": "Rețele permise", "Alphabetic": "Alfabetic", + "Altered by ignoring deletes.": "Modificat prin ignorarea ștergerilor.", "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.": "O comandă externă gestionează versiunea. Trebuie să elimine fișierul din mapa partajat. Dacă calea către aplicație conține spații, ar trebui să fie pusă între ghilimele.", "Anonymous Usage Reporting": "Raport Anonim despre Folosirea Aplicației", "Anonymous usage report format has changed. Would you like to move to the new format?": "Formatul raportului de utilizare anonim s-a schimbat. Doriți să vă mutați în noul format?", diff --git a/gui/default/assets/lang/lang-sr.json b/gui/default/assets/lang/lang-sr.json index 2c63c0851..b94ad4e12 100644 --- a/gui/default/assets/lang/lang-sr.json +++ b/gui/default/assets/lang/lang-sr.json @@ -1,2 +1,36 @@ { + "A device with that ID is already added.": "Уређај са тим идентификатором је већ додат.", + "A negative number of days doesn't make sense.": "Негативан број дана нема смисла.", + "A new major version may not be compatible with previous versions.": "Нова верзија можда неће радити са претходним верзијама.", + "API Key": "АПИ кључ", + "About": "Информације", + "Action": "Радња", + "Actions": "Радње", + "Active filter rules": "Активна правила филтера", + "Add": "Додај", + "Add Device": "Додај уређај", + "Add Folder": "Додај фасциклу", + "Add Remote Device": "Додаај удаљени уређај", + "Add devices from the introducer to our device list, for mutually shared folders.": "Додај уређаје од иницијатора на нашу листу уређаја, за међусобно дељене фасцикле.", + "Add filter entry": "Додај ставку филтера", + "Add ignore patterns": "Додај правила за игнорисање", + "Add new folder?": "Додај нову фасциклу?", + "Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Додатно, интервал потпуног поновног скенирања ће бити повећан (60 пута, тј. нови подразумевани интервал од 1 сат). Такође можете ручно да га подесите за сваку фасциклу касније након што изаберете Не.", + "Address": "Адреса", + "Addresses": "Адресе", + "Advanced": "Напредно", + "Advanced Configuration": "Напредна конфигурација", + "All Data": "Сви подаци", + "All Time": "Све време", + "All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Све фасцикле које се деле са овим уређајем морају бити заштићене лозинком, тако да сви послати подаци не могу бити прочитани без дате лозинке.", + "Allow Anonymous Usage Reporting?": "Дозволити анонимно слање података о коришћењу?", + "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?": "Формат анонимног слања података о коришћењу је промењен. Желите ли да пређете на нови формат?", + "Applied to LAN": "Важи за локалну мрежу", + "Apply": "Примени" } diff --git a/gui/default/syncthing/core/aboutModalView.html b/gui/default/syncthing/core/aboutModalView.html index d040801fa..6652120b7 100644 --- a/gui/default/syncthing/core/aboutModalView.html +++ b/gui/default/syncthing/core/aboutModalView.html @@ -30,7 +30,7 @@

The Syncthing Authors

-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, 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, Ashish Bhate, 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, pullmerge, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
diff --git a/man/stdiscosrv.1 b/man/stdiscosrv.1 index f56c8df43..d5e0831eb 100644 --- a/man/stdiscosrv.1 +++ b/man/stdiscosrv.1 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "STDISCOSRV" "1" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME stdiscosrv \- Syncthing Discovery Server .SH SYNOPSIS diff --git a/man/strelaysrv.1 b/man/strelaysrv.1 index d175a9a45..d617a6632 100644 --- a/man/strelaysrv.1 +++ b/man/strelaysrv.1 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "STRELAYSRV" "1" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME strelaysrv \- Syncthing Relay Server .SH SYNOPSIS diff --git a/man/syncthing-bep.7 b/man/syncthing-bep.7 index e1d024289..7cd86dfc0 100644 --- a/man/syncthing-bep.7 +++ b/man/syncthing-bep.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-BEP" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-bep \- Block Exchange Protocol v1 .SH INTRODUCTION AND DEFINITIONS diff --git a/man/syncthing-config.5 b/man/syncthing-config.5 index 168cabc24..60478e60a 100644 --- a/man/syncthing-config.5 +++ b/man/syncthing-config.5 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-CONFIG" "5" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-config \- Syncthing Configuration .SH SYNOPSIS diff --git a/man/syncthing-device-ids.7 b/man/syncthing-device-ids.7 index 5539b2bb4..d17001e3f 100644 --- a/man/syncthing-device-ids.7 +++ b/man/syncthing-device-ids.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-DEVICE-IDS" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-device-ids \- Understanding Device IDs .sp diff --git a/man/syncthing-event-api.7 b/man/syncthing-event-api.7 index 55491c193..d8bf2a5a0 100644 --- a/man/syncthing-event-api.7 +++ b/man/syncthing-event-api.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-EVENT-API" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-event-api \- Event API .SH DESCRIPTION diff --git a/man/syncthing-faq.7 b/man/syncthing-faq.7 index fe3cf33c3..ce59664e2 100644 --- a/man/syncthing-faq.7 +++ b/man/syncthing-faq.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-FAQ" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-faq \- Frequently Asked Questions .INDENT 0.0 diff --git a/man/syncthing-globaldisco.7 b/man/syncthing-globaldisco.7 index bf207e6df..b09d2ca2a 100644 --- a/man/syncthing-globaldisco.7 +++ b/man/syncthing-globaldisco.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-GLOBALDISCO" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-globaldisco \- Global Discovery Protocol v3 .SH ANNOUNCEMENTS diff --git a/man/syncthing-localdisco.7 b/man/syncthing-localdisco.7 index 8fe9af457..46526c13c 100644 --- a/man/syncthing-localdisco.7 +++ b/man/syncthing-localdisco.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-LOCALDISCO" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-localdisco \- Local Discovery Protocol v4 .SH MODE OF OPERATION diff --git a/man/syncthing-networking.7 b/man/syncthing-networking.7 index 4dda7e1a5..4d04dea7f 100644 --- a/man/syncthing-networking.7 +++ b/man/syncthing-networking.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-NETWORKING" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-networking \- Firewall Setup .SH ROUTER SETUP diff --git a/man/syncthing-relay.7 b/man/syncthing-relay.7 index f0e91887d..7573ebf86 100644 --- a/man/syncthing-relay.7 +++ b/man/syncthing-relay.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-RELAY" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-relay \- Relay Protocol v1 .SH WHAT IS A RELAY? diff --git a/man/syncthing-rest-api.7 b/man/syncthing-rest-api.7 index e26c33836..94abbf5d0 100644 --- a/man/syncthing-rest-api.7 +++ b/man/syncthing-rest-api.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-REST-API" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-rest-api \- REST API .sp diff --git a/man/syncthing-security.7 b/man/syncthing-security.7 index d5069febe..16b9e2510 100644 --- a/man/syncthing-security.7 +++ b/man/syncthing-security.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-SECURITY" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-security \- Security Principles .sp diff --git a/man/syncthing-stignore.5 b/man/syncthing-stignore.5 index 7c7f7a58b..6e5e24dd0 100644 --- a/man/syncthing-stignore.5 +++ b/man/syncthing-stignore.5 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-STIGNORE" "5" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-stignore \- Prevent files from being synchronized to other nodes .SH SYNOPSIS diff --git a/man/syncthing-versioning.7 b/man/syncthing-versioning.7 index 092db8789..070fa33b7 100644 --- a/man/syncthing-versioning.7 +++ b/man/syncthing-versioning.7 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING-VERSIONING" "7" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing-versioning \- Keep automatic backups of deleted files by other nodes .sp diff --git a/man/syncthing.1 b/man/syncthing.1 index 7b1e64482..6697a5991 100644 --- a/man/syncthing.1 +++ b/man/syncthing.1 @@ -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 15, 2025" "v1.29.6" "Syncthing" +.TH "SYNCTHING" "1" "May 25, 2025" "v1.29.6" "Syncthing" .SH NAME syncthing \- Syncthing .SH SYNOPSIS From 58c85fc9dbb8c56cd1cea70962b8f7bbb79e7329 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Mon, 26 May 2025 13:33:53 +0200 Subject: [PATCH 2/5] build: process for automatic release tags (#10133) Make the release tagging consistent. Push to release branch to create a stable release; push to release-rc to release a new candidate. --- .github/workflows/build-syncthing.yaml | 36 ++++++-- .github/workflows/release-syncthing.yaml | 55 ++++++++++++ relnotes/README.md | 18 ++++ script/relnotes.go | 109 +++++++++++++++++++++++ 4 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/release-syncthing.yaml create mode 100644 relnotes/README.md create mode 100644 script/relnotes.go diff --git a/.github/workflows/build-syncthing.yaml b/.github/workflows/build-syncthing.yaml index 78aab4d37..c5ae6f9dc 100644 --- a/.github/workflows/build-syncthing.yaml +++ b/.github/workflows/build-syncthing.yaml @@ -173,7 +173,7 @@ jobs: codesign-windows: name: Codesign for Windows - if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v')) + if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) environment: release runs-on: windows-latest needs: @@ -280,7 +280,7 @@ jobs: package-macos: name: Package for macOS - if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v')) + if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) environment: release runs-on: macos-latest steps: @@ -380,7 +380,7 @@ jobs: notarize-macos: name: Notarize for macOS - if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v')) + if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) environment: release needs: - package-macos @@ -524,7 +524,7 @@ jobs: sign-for-upgrade: name: Sign for upgrade - if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v')) + if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) environment: release needs: - codesign-windows @@ -723,6 +723,8 @@ jobs: name: Publish release files if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/tags/v')) environment: release + permissions: + contents: write needs: - sign-for-upgrade - package-debian @@ -782,13 +784,35 @@ jobs: with: args: sync -v objstore:release/${{ env.VERSION }} objstore:release/latest + - name: Create GitHub release and push binaries + run: | + maybePrerelease="" + if [[ $VERSION == *-* ]]; then + maybePrerelease="--prerelease" + fi + export GH_PROMPT_DISABLED=1 + if ! gh release view --json name "$VERSION" >/dev/null 2>&1 ; then + gh release create \ + "$VERSION" \ + $maybePrerelease \ + --title "$VERSION" \ + --notes-from-tag + fi + gh release upload "$VERSION" \ + packages/*.asc packages/*.json \ + packages/syncthing-*.tar.gz \ + packages/syncthing-*.zip \ + packages/syncthing*.deb + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # # Push Debian/APT archive # publish-apt: name: Publish APT - if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v')) + if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/release-nightly' || startsWith(github.ref, 'refs/tags/v')) environment: release needs: - package-debian @@ -867,7 +891,7 @@ jobs: docker-syncthing: name: Build and push Docker images runs-on: ubuntu-latest - if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release' || github.ref == 'refs/heads/infrastructure' || startsWith(github.ref, 'refs/heads/release-') || startsWith(github.ref, 'refs/tags/v')) + if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release-nightly' || github.ref == 'refs/heads/infrastructure' || startsWith(github.ref, 'refs/tags/v')) environment: docker permissions: contents: read diff --git a/.github/workflows/release-syncthing.yaml b/.github/workflows/release-syncthing.yaml new file mode 100644 index 000000000..209a64d54 --- /dev/null +++ b/.github/workflows/release-syncthing.yaml @@ -0,0 +1,55 @@ +name: Release Syncthing + +on: + push: + branches: + - release + - release-rc* + +permissions: + contents: write + +jobs: + create-release-tag: + name: Create release tag + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882 + + - uses: actions/setup-go@v5 + with: + go-version: stable + + - name: Get svu + run: | + go install github.com/caarlos0/svu@latest + + - name: Determine version to release + run: | + if [[ "$GITHUB_REF_NAME" == "release" ]] ; then + next=$(svu next) + else + next=$(svu prerelease --pre-release rc) + fi + echo "NEXT=$next" >> $GITHUB_ENV + echo "Next version is $next" + + prev=$(git describe --exclude "*-*" --abbrev=0) + echo "PREV=$prev" >> $GITHUB_ENV + echo "Previous version is $prev" + + - name: Determine release notes + run: | + go run ./script/relnotes.go --new-ver "$NEXT" --branch "$GITHUB_REF_NAME" --prev-ver "$PREV" > notes.md + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create and push tag + run: | + git config --global user.name 'Syncthing Release Automation' + git config --global user.email 'release@syncthing.net' + git tag -a -F notes.md "$NEXT" + git push origin "$NEXT" diff --git a/relnotes/README.md b/relnotes/README.md new file mode 100644 index 000000000..66a4991c6 --- /dev/null +++ b/relnotes/README.md @@ -0,0 +1,18 @@ +# Release Notes + +Files in this directory constitute manual release notes for a given release. +When relevant, they should be created prior to that release so that they can +be included in the corresponding tag message, etc. + +To add release notes for a release 1.2.3, create a file named `v1.2.3.md` +consisting of an initial H2-level header and further notes as desired. For +example: + +``` +## Major changes in v1.2.3 + +- Files are now synchronized twice as fast on Tuesdays +``` + +The release notes will also be included in candidate releases (e.g. +v1.2.3-rc.1). diff --git a/script/relnotes.go b/script/relnotes.go new file mode 100644 index 000000000..ffc27c22f --- /dev/null +++ b/script/relnotes.go @@ -0,0 +1,109 @@ +// 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/. + +//go:build ignore +// +build ignore + +package main + +import ( + "bytes" + "cmp" + "encoding/json" + "errors" + "flag" + "fmt" + "io" + "log" + "net/http" + "os" + "strings" +) + +var ( + githubToken = os.Getenv("GITHUB_TOKEN") + githubRepo = cmp.Or(os.Getenv("GITHUB_REPOSITORY"), "syncthing/syncthing") +) + +func main() { + ver := flag.String("new-ver", "", "New version tag") + prevVer := flag.String("prev-ver", "", "Previous version tag") + branch := flag.String("branch", "HEAD", "Branch to release from") + flag.Parse() + + log.SetOutput(os.Stderr) + + if *ver == "" { + log.Fatalln("Must set --new-ver") + } + if githubToken == "" { + log.Fatalln("Must set $GITHUB_TOKEN") + } + + addl, err := additionalNotes(*ver) + if err != nil { + log.Fatalln("Gathering additional notes:", err) + } + notes, err := generatedNotes(*ver, *branch, *prevVer) + if err != nil { + log.Fatalln("Gathering github notes:", err) + } + + if addl != "" { + fmt.Println(addl) + } + fmt.Println(notes) +} + +// Load potential additional release notes from within the repo +func additionalNotes(newVer string) (string, error) { + ver, _, _ := strings.Cut(newVer, "-") + bs, err := os.ReadFile(fmt.Sprintf("relnotes/%s.md", ver)) + if os.IsNotExist(err) { + return "", nil + } + return string(bs), err +} + +// Load generated release notes (list of pull requests and contributors) +// from GitHub. +func generatedNotes(newVer, targetCommit, prevVer string) (string, error) { + fields := map[string]string{ + "tag_name": newVer, + "target_commitish": targetCommit, + "previous_tag_name": prevVer, + } + bs, err := json.Marshal(fields) + if err != nil { + return "", err + } + req, err := http.NewRequest(http.MethodPost, "https://api.github.com/repos/"+githubRepo+"/releases/generate-notes", bytes.NewReader(bs)) //nolint:noctx + if err != nil { + return "", err + } + + req.Header.Set("Accept", "application/vnd.github+json") + req.Header.Set("Authorization", "Bearer "+githubToken) + req.Header.Set("X-Github-Api-Version", "2022-11-28") + res, err := http.DefaultClient.Do(req) + if err != nil { + return "", err + } + if res.StatusCode != http.StatusOK { + bs, _ := io.ReadAll(res.Body) + log.Print(string(bs)) + return "", errors.New(res.Status) //nolint:err113 + } + defer res.Body.Close() + + var resJSON struct { + Body string + } + if err := json.NewDecoder(res.Body).Decode(&resJSON); err != nil { + return "", err + } + return resJSON.Body, nil +} From 48b757cac1fb908555abf2864632d47d97e8fed3 Mon Sep 17 00:00:00 2001 From: Marcel Meyer Date: Mon, 26 May 2025 13:37:26 +0200 Subject: [PATCH 3/5] refactor: use slices package for sort (#10132) The sort package is still used in places that were not trivial to change. Since Go 1.21 slices package can be uswed for sort. See https://go.dev/doc/go1.21#slices ### Purpose Make some progress with the migration to a more up-to-date syntax. --- cmd/infra/stcrashreceiver/diskstore.go | 7 ++++--- cmd/syncthing/cli/index_dumpsize.go | 7 ++++--- cmd/syncthing/cli/index_idxck.go | 11 ++++++----- cmd/syncthing/main.go | 4 ++-- lib/api/api.go | 15 ++++++++------- lib/build/build.go | 4 ++-- lib/config/config.go | 5 +++-- lib/config/config_test.go | 4 ++-- lib/config/migrations.go | 9 +++++---- lib/config/versioningconfiguration.go | 7 ++++--- lib/connections/service.go | 3 +-- lib/db/smallindex.go | 4 ++-- lib/discover/manager.go | 4 ++-- lib/fs/basicfs_test.go | 13 ++++++------- lib/fs/basicfs_xattr_bsdish.go | 4 ++-- lib/fs/basicfs_xattr_linuxish.go | 4 ++-- lib/fs/casefs_test.go | 4 ++-- lib/fs/fakefs_test.go | 6 +++--- lib/model/folder.go | 3 ++- lib/model/model_test.go | 5 ++--- lib/relay/client/dynamic.go | 4 ++-- lib/syncthing/syncthing.go | 6 +++--- lib/ur/usage_report.go | 6 +++--- lib/versioner/simple.go | 4 ++-- lib/versioner/staggered.go | 4 ++-- lib/versioner/staggered_test.go | 6 +++--- lib/versioner/util.go | 4 ++-- script/transifexdl.go | 4 ++-- script/weblatedl.go | 4 ++-- 29 files changed, 85 insertions(+), 80 deletions(-) diff --git a/cmd/infra/stcrashreceiver/diskstore.go b/cmd/infra/stcrashreceiver/diskstore.go index 124d77d4a..fca0fdc01 100644 --- a/cmd/infra/stcrashreceiver/diskstore.go +++ b/cmd/infra/stcrashreceiver/diskstore.go @@ -8,6 +8,7 @@ package main import ( "bytes" + "cmp" "compress/gzip" "context" "io" @@ -15,7 +16,7 @@ import ( "math" "os" "path/filepath" - "sort" + "slices" "time" ) @@ -177,8 +178,8 @@ func (d *diskStore) inventory() error { }) return nil }) - sort.Slice(d.currentFiles, func(i, j int) bool { - return d.currentFiles[i].mtime < d.currentFiles[j].mtime + slices.SortFunc(d.currentFiles, func(a, b currentFile) int { + return cmp.Compare(a.mtime, b.mtime) }) var oldest time.Duration if len(d.currentFiles) > 0 { diff --git a/cmd/syncthing/cli/index_dumpsize.go b/cmd/syncthing/cli/index_dumpsize.go index da7a6dbe6..17cfa61c4 100644 --- a/cmd/syncthing/cli/index_dumpsize.go +++ b/cmd/syncthing/cli/index_dumpsize.go @@ -7,9 +7,10 @@ package cli import ( + "cmp" "encoding/binary" "fmt" - "sort" + "slices" "github.com/syncthing/syncthing/lib/db" ) @@ -77,8 +78,8 @@ func indexDumpSize() error { elems = append(elems, ele) } - sort.Slice(elems, func(i, j int) bool { - return elems[i].size > elems[j].size + slices.SortFunc(elems, func(a, b sizedElement) int { + return cmp.Compare(b.size, a.size) }) for _, ele := range elems { fmt.Println(ele.key, ele.size) diff --git a/cmd/syncthing/cli/index_idxck.go b/cmd/syncthing/cli/index_idxck.go index a0dab459a..4e1cbc181 100644 --- a/cmd/syncthing/cli/index_idxck.go +++ b/cmd/syncthing/cli/index_idxck.go @@ -8,10 +8,11 @@ package cli import ( "bytes" + "cmp" "encoding/binary" "errors" "fmt" - "sort" + "slices" "google.golang.org/protobuf/proto" @@ -207,11 +208,11 @@ func indexCheck() (err error) { // Aggregate the ranges of missing sequence entries, print them - sort.Slice(missingSeq, func(a, b int) bool { - if missingSeq[a].folder != missingSeq[b].folder { - return missingSeq[a].folder < missingSeq[b].folder + slices.SortFunc(missingSeq, func(a, b sequenceKey) int { + if a.folder != b.folder { + return cmp.Compare(a.folder, b.folder) } - return missingSeq[a].sequence < missingSeq[b].sequence + return cmp.Compare(a.sequence, b.sequence) }) var folder uint32 diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 6a1185d98..458f0761e 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -23,7 +23,7 @@ import ( "path/filepath" "regexp" "runtime/pprof" - "sort" + "slices" "strconv" "strings" "syscall" @@ -443,7 +443,7 @@ func debugFacilities() string { maxLen = len(name) } } - sort.Strings(names) + slices.Sort(names) // Format the choices b := new(bytes.Buffer) diff --git a/lib/api/api.go b/lib/api/api.go index 8d07546b9..1115926cc 100644 --- a/lib/api/api.go +++ b/lib/api/api.go @@ -8,6 +8,7 @@ package api import ( "bytes" + "cmp" "context" "crypto/tls" "crypto/x509" @@ -24,7 +25,7 @@ import ( "reflect" "runtime" "runtime/pprof" - "sort" + "slices" "strconv" "strings" "time" @@ -750,7 +751,7 @@ func (*service) getSystemVersion(w http.ResponseWriter, _ *http.Request) { func (*service) getSystemDebug(w http.ResponseWriter, _ *http.Request) { names := l.Facilities() enabled := l.FacilityDebugging() - sort.Strings(enabled) + slices.Sort(enabled) sendJSON(w, map[string]interface{}{ "facilities": names, "enabled": enabled, @@ -1535,8 +1536,8 @@ func (*service) getLang(w http.ResponseWriter, r *http.Request) { langs = append(langs, code) } // Reorder by descending q value - sort.SliceStable(langs, func(i, j int) bool { - return weights[langs[i]] > weights[langs[j]] + slices.SortStableFunc(langs, func(i, j string) int { + return cmp.Compare(weights[j], weights[i]) }) sendJSON(w, langs) } @@ -1822,8 +1823,8 @@ func browseFiles(ffs fs.Filesystem, search string) []string { } // sort to return matches in deterministic order (don't depend on file system order) - sort.Strings(exactMatches) - sort.Strings(caseInsMatches) + slices.Sort(exactMatches) + slices.Sort(caseInsMatches) return append(exactMatches, caseInsMatches...) } @@ -1920,7 +1921,7 @@ func dirNames(dir string) []string { } } - sort.Strings(dirs) + slices.Sort(dirs) return dirs } diff --git a/lib/build/build.go b/lib/build/build.go index 098dd7c7c..a07682451 100644 --- a/lib/build/build.go +++ b/lib/build/build.go @@ -12,7 +12,7 @@ import ( "os" "regexp" "runtime" - "sort" + "slices" "strconv" "strings" "time" @@ -109,7 +109,7 @@ func TagsList() []string { tags = append(tags, Extra) } - sort.Strings(tags) + slices.Sort(tags) return tags } diff --git a/lib/config/config.go b/lib/config/config.go index 73c48ecd0..740054726 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -17,6 +17,7 @@ import ( "net/url" "os" "reflect" + "slices" "sort" "strconv" "strings" @@ -380,8 +381,8 @@ func (cfg *Configuration) prepareFolders(myID protocol.DeviceID, existingDevices } } // Ensure that the folder list is sorted by ID - sort.Slice(cfg.Folders, func(a, b int) bool { - return cfg.Folders[a].ID < cfg.Folders[b].ID + slices.SortFunc(cfg.Folders, func(a, b FolderConfiguration) int { + return strings.Compare(a.ID, b.ID) }) return sharedFolders, nil } diff --git a/lib/config/config_test.go b/lib/config/config_test.go index 27cfdd879..8031fadb9 100644 --- a/lib/config/config_test.go +++ b/lib/config/config_test.go @@ -17,7 +17,7 @@ import ( "path/filepath" "reflect" "runtime" - "sort" + "slices" "strings" "testing" @@ -911,7 +911,7 @@ func TestV14ListenAddressesMigration(t *testing.T) { t.Error("Configuration was not converted") } - sort.Strings(tc[2]) + slices.Sort(tc[2]) if !reflect.DeepEqual(cfg.Options.RawListenAddresses, tc[2]) { t.Errorf("Migration error; actual %#v != expected %#v", cfg.Options.RawListenAddresses, tc[2]) } diff --git a/lib/config/migrations.go b/lib/config/migrations.go index 4a4ecdf37..838d0154f 100644 --- a/lib/config/migrations.go +++ b/lib/config/migrations.go @@ -7,11 +7,12 @@ package config import ( + "cmp" "net/url" "os" "path" "path/filepath" - "sort" + "slices" "strings" "sync" @@ -65,8 +66,8 @@ type migrationSet []migration func (ms migrationSet) apply(cfg *Configuration) { // Make sure we apply the migrations in target version order regardless // of how it was defined. - sort.Slice(ms, func(a, b int) bool { - return ms[a].targetVersion < ms[b].targetVersion + slices.SortFunc(ms, func(a, b migration) int { + return cmp.Compare(a.targetVersion, b.targetVersion) }) // Apply all migrations. @@ -349,7 +350,7 @@ func migrateToConfigV14(cfg *Configuration) { cfg.Options.DeprecatedRelayServers = nil // For consistency - sort.Strings(cfg.Options.RawListenAddresses) + slices.Sort(cfg.Options.RawListenAddresses) var newAddrs []string for _, addr := range cfg.Options.RawGlobalAnnServers { diff --git a/lib/config/versioningconfiguration.go b/lib/config/versioningconfiguration.go index 988f8ab44..66327aa8e 100644 --- a/lib/config/versioningconfiguration.go +++ b/lib/config/versioningconfiguration.go @@ -9,7 +9,8 @@ package config import ( "encoding/json" "encoding/xml" - "sort" + "slices" + "strings" "github.com/syncthing/syncthing/lib/structutil" ) @@ -84,8 +85,8 @@ func (c *VersioningConfiguration) toInternal() internalVersioningConfiguration { 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 + slices.SortFunc(tmp.Params, func(a, b internalParam) int { + return strings.Compare(a.Key, b.Key) }) return tmp } diff --git a/lib/connections/service.go b/lib/connections/service.go index be432d37e..f548d0e9f 100644 --- a/lib/connections/service.go +++ b/lib/connections/service.go @@ -23,7 +23,6 @@ import ( "net" "net/url" "slices" - "sort" "strings" stdsync "sync" "time" @@ -1151,7 +1150,7 @@ func (s *service) dialParallel(ctx context.Context, deviceID protocol.DeviceID, } // Sort the priorities so that we dial lowest first (which means highest...) - sort.Ints(priorities) + slices.Sort(priorities) sema := semaphore.MultiSemaphore{semaphore.New(dialMaxParallelPerDevice), parentSema} for _, prio := range priorities { diff --git a/lib/db/smallindex.go b/lib/db/smallindex.go index b426d906b..c53c69804 100644 --- a/lib/db/smallindex.go +++ b/lib/db/smallindex.go @@ -8,7 +8,7 @@ package db import ( "encoding/binary" - "sort" + "slices" "github.com/syncthing/syncthing/lib/db/backend" "github.com/syncthing/syncthing/lib/sync" @@ -147,6 +147,6 @@ func (i *smallIndex) Values() []string { } i.mut.Unlock() - sort.Strings(vals) + slices.Sort(vals) return vals } diff --git a/lib/discover/manager.go b/lib/discover/manager.go index 4cec90dce..4c12fbf31 100644 --- a/lib/discover/manager.go +++ b/lib/discover/manager.go @@ -13,7 +13,7 @@ import ( "context" "crypto/tls" "fmt" - "sort" + "slices" "time" "github.com/thejerf/suture/v4" @@ -159,7 +159,7 @@ func (m *manager) Lookup(ctx context.Context, deviceID protocol.DeviceID) (addre m.mut.RUnlock() addresses = stringutil.UniqueTrimmedStrings(addresses) - sort.Strings(addresses) + slices.Sort(addresses) l.Debugln("lookup results for", deviceID) l.Debugln(" addresses: ", addresses) diff --git a/lib/fs/basicfs_test.go b/lib/fs/basicfs_test.go index 66306f8f8..4d194f3ed 100644 --- a/lib/fs/basicfs_test.go +++ b/lib/fs/basicfs_test.go @@ -12,7 +12,7 @@ import ( "fmt" "os" "path/filepath" - "sort" + "slices" "strconv" "strings" "syscall" @@ -218,7 +218,7 @@ func TestDirNames(t *testing.T) { "a", "bC", } - sort.Strings(testCases) + slices.Sort(testCases) for _, sub := range testCases { if err := os.Mkdir(filepath.Join(dir, sub), 0o777); err != nil { @@ -229,7 +229,7 @@ func TestDirNames(t *testing.T) { if dirs, err := fs.DirNames("."); err != nil || len(dirs) != len(testCases) { t.Errorf("%s %s %s", err, dirs, testCases) } else { - sort.Strings(dirs) + slices.Sort(dirs) for i := range dirs { if dirs[i] != testCases[i] { t.Errorf("%s != %s", dirs[i], testCases[i]) @@ -321,8 +321,8 @@ func TestGlob(t *testing.T) { for _, testCase := range testCases { results, err := fs.Glob(testCase.pattern) - sort.Strings(results) - sort.Strings(testCase.matches) + slices.Sort(results) + slices.Sort(testCase.matches) if err != nil { t.Error(err) } @@ -628,8 +628,7 @@ func TestXattr(t *testing.T) { Value: value, }) } - sort.Slice(attrs, func(i, j int) bool { return attrs[i].Name < attrs[j].Name }) - + slices.SortFunc(attrs, func(a, b protocol.Xattr) int { return strings.Compare(a.Name, b.Name) }) // Set the xattrs, read them back and compare if err := tfs.SetXattr("/test", attrs, testXattrFilter{}); err != nil { t.Fatal(err) diff --git a/lib/fs/basicfs_xattr_bsdish.go b/lib/fs/basicfs_xattr_bsdish.go index a10c3ee3e..c22d2b73c 100644 --- a/lib/fs/basicfs_xattr_bsdish.go +++ b/lib/fs/basicfs_xattr_bsdish.go @@ -12,7 +12,7 @@ package fs import ( "errors" "fmt" - "sort" + "slices" "unsafe" "golang.org/x/sys/unix" @@ -69,7 +69,7 @@ func listXattr(path string) ([]string, error) { } } - sort.Strings(attrs) + slices.Sort(attrs) return attrs, nil } diff --git a/lib/fs/basicfs_xattr_linuxish.go b/lib/fs/basicfs_xattr_linuxish.go index 4857a4098..4df9921d8 100644 --- a/lib/fs/basicfs_xattr_linuxish.go +++ b/lib/fs/basicfs_xattr_linuxish.go @@ -12,7 +12,7 @@ package fs import ( "errors" "fmt" - "sort" + "slices" "strings" "golang.org/x/sys/unix" @@ -38,6 +38,6 @@ func listXattr(path string) ([]string, error) { buf = buf[:size] attrs := compact(strings.Split(string(buf), "\x00")) - sort.Strings(attrs) + slices.Sort(attrs) return attrs, nil } diff --git a/lib/fs/casefs_test.go b/lib/fs/casefs_test.go index 8bd78cb57..10329b36a 100644 --- a/lib/fs/casefs_test.go +++ b/lib/fs/casefs_test.go @@ -11,7 +11,7 @@ import ( "fmt" "path/filepath" "runtime" - "sort" + "slices" "strings" "testing" "time" @@ -344,7 +344,7 @@ func fakefsForBenchmark(nfiles int, latency time.Duration) (Filesystem, []string return nil, nil, errors.New("didn't find enough stuff") } - sort.Strings(paths) + slices.Sort(paths) return fsys, paths, nil } diff --git a/lib/fs/fakefs_test.go b/lib/fs/fakefs_test.go index 770461114..74d58eabe 100644 --- a/lib/fs/fakefs_test.go +++ b/lib/fs/fakefs_test.go @@ -14,7 +14,7 @@ import ( "path" "path/filepath" "runtime" - "sort" + "slices" "testing" "time" @@ -369,8 +369,8 @@ func assertDir(t *testing.T, fs Filesystem, directory string, filenames []string if path.Clean(directory) == "/" { filenames = append(filenames, ".stfolder") } - sort.Strings(filenames) - sort.Strings(got) + slices.Sort(filenames) + slices.Sort(got) if len(filenames) != len(got) { t.Errorf("want %s, got %s", filenames, got) diff --git a/lib/model/folder.go b/lib/model/folder.go index f8b8c501f..a0c342158 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -12,6 +12,7 @@ import ( "fmt" "math/rand" "path/filepath" + "slices" "sort" "time" @@ -1341,7 +1342,7 @@ func unifySubs(dirs []string, exists func(dir string) bool) []string { if len(dirs) == 0 { return nil } - sort.Strings(dirs) + slices.Sort(dirs) if dirs[0] == "" || dirs[0] == "." || dirs[0] == string(fs.PathSeparator) { return nil } diff --git a/lib/model/model_test.go b/lib/model/model_test.go index f7399e4d9..e14834464 100644 --- a/lib/model/model_test.go +++ b/lib/model/model_test.go @@ -18,7 +18,6 @@ import ( "path/filepath" "runtime/pprof" "slices" - "sort" "strconv" "strings" "sync" @@ -4092,8 +4091,8 @@ func equalStringsInAnyOrder(a, b []string) bool { if len(a) != len(b) { return false } - sort.Strings(a) - sort.Strings(b) + slices.Sort(a) + slices.Sort(b) for i := range a { if a[i] != b[i] { return false diff --git a/lib/relay/client/dynamic.go b/lib/relay/client/dynamic.go index baef98df3..8ab7d5ad2 100644 --- a/lib/relay/client/dynamic.go +++ b/lib/relay/client/dynamic.go @@ -10,7 +10,7 @@ import ( "fmt" "net/http" "net/url" - "sort" + "slices" "sync" "time" @@ -166,7 +166,7 @@ func relayAddressesOrder(ctx context.Context, input []string) []string { ids = append(ids, id) } - sort.Ints(ids) + slices.Sort(ids) addresses := make([]string, 0, len(input)) for _, id := range ids { diff --git a/lib/syncthing/syncthing.go b/lib/syncthing/syncthing.go index e43a04d25..733a095e7 100644 --- a/lib/syncthing/syncthing.go +++ b/lib/syncthing/syncthing.go @@ -15,7 +15,7 @@ import ( "net/http" "os" "runtime" - "sort" + "slices" "strings" "sync" "time" @@ -437,8 +437,8 @@ func printServiceTree(w io.Writer, sup supervisor, level int) { printService(w, sup, level) svcs := sup.Services() - sort.Slice(svcs, func(a, b int) bool { - return fmt.Sprint(svcs[a]) < fmt.Sprint(svcs[b]) + slices.SortFunc(svcs, func(a, b suture.Service) int { + return strings.Compare(fmt.Sprint(a), fmt.Sprint(b)) }) for _, svc := range svcs { diff --git a/lib/ur/usage_report.go b/lib/ur/usage_report.go index 21aea826e..c80168738 100644 --- a/lib/ur/usage_report.go +++ b/lib/ur/usage_report.go @@ -16,7 +16,7 @@ import ( "net/http" "os" "runtime" - "sort" + "slices" "strings" "sync" "time" @@ -162,7 +162,7 @@ func (s *Service) reportData(ctx context.Context, urVersion int, preview bool) ( l.Warnf("Unhandled versioning type for usage reports: %s", cfg.Versioning.Type) } } - sort.Ints(report.RescanIntvs) + slices.Sort(report.RescanIntvs) for _, cfg := range s.cfg.Devices() { if cfg.Introducer { @@ -295,7 +295,7 @@ func (s *Service) reportData(ctx context.Context, urVersion int, preview bool) ( report.FolderUsesV3.SyncOwnership++ } } - sort.Ints(report.FolderUsesV3.FsWatcherDelays) + slices.Sort(report.FolderUsesV3.FsWatcherDelays) for _, cfg := range s.cfg.Devices() { if cfg.Untrusted { diff --git a/lib/versioner/simple.go b/lib/versioner/simple.go index f56a8279b..24b861346 100644 --- a/lib/versioner/simple.go +++ b/lib/versioner/simple.go @@ -8,7 +8,7 @@ package versioner import ( "context" - "sort" + "slices" "strconv" "time" @@ -79,7 +79,7 @@ func (v simple) toRemove(versions []string, now time.Time) []string { var remove []string // The list of versions may or may not be properly sorted. - sort.Strings(versions) + slices.Sort(versions) // If the amount of elements exceeds the limit: the oldest elements are to be removed. if len(versions) > v.keep { diff --git a/lib/versioner/staggered.go b/lib/versioner/staggered.go index e97c2e6d4..9bb56488a 100644 --- a/lib/versioner/staggered.go +++ b/lib/versioner/staggered.go @@ -9,7 +9,7 @@ package versioner import ( "context" "fmt" - "sort" + "slices" "strconv" "time" @@ -69,7 +69,7 @@ func (v *staggered) toRemove(versions []string, now time.Time) []string { var remove []string // The list of versions may or may not be properly sorted. - sort.Strings(versions) + slices.Sort(versions) for _, version := range versions { versionTime, err := time.ParseInLocation(TimeFormat, extractTag(version), time.Local) diff --git a/lib/versioner/staggered_test.go b/lib/versioner/staggered_test.go index 534705599..0e6623b80 100644 --- a/lib/versioner/staggered_test.go +++ b/lib/versioner/staggered_test.go @@ -9,7 +9,7 @@ package versioner import ( "os" "path/filepath" - "sort" + "slices" "strconv" "testing" "time" @@ -97,7 +97,7 @@ func TestStaggeredVersioningVersionCount(t *testing.T) { "test~20150416-135958", // 365 days 2 seconds ago "test~20150414-140000", // 367 days ago } - sort.Strings(delete) + slices.Sort(delete) cfg := config.FolderConfiguration{ FilesystemType: config.FilesystemTypeBasic, @@ -111,7 +111,7 @@ func TestStaggeredVersioningVersionCount(t *testing.T) { v := newStaggered(cfg).(*staggered) rem := v.toRemove(versionsWithMtime, now) - sort.Strings(rem) + slices.Sort(rem) if diff, equal := messagediff.PrettyDiff(delete, rem); !equal { t.Errorf("Incorrect deleted files; got %v, expected %v\n%v", rem, delete, diff) diff --git a/lib/versioner/util.go b/lib/versioner/util.go index 66d8c90ba..070cdf5bb 100644 --- a/lib/versioner/util.go +++ b/lib/versioner/util.go @@ -13,7 +13,7 @@ import ( "os" "path/filepath" "regexp" - "sort" + "slices" "strings" "time" @@ -339,7 +339,7 @@ func findAllVersions(fs fs.Filesystem, filePath string) []string { return nil } versions = stringutil.UniqueTrimmedStrings(versions) - sort.Strings(versions) + slices.Sort(versions) return versions } diff --git a/script/transifexdl.go b/script/transifexdl.go index abb5291cf..bd7ee79e1 100644 --- a/script/transifexdl.go +++ b/script/transifexdl.go @@ -17,7 +17,7 @@ import ( "net/http" "os" "regexp" - "sort" + "slices" "strings" ) @@ -93,7 +93,7 @@ func main() { } func saveValidLangs(langs []string) { - sort.Strings(langs) + slices.Sort(langs) fd, err := os.Create("valid-langs.js") if err != nil { log.Fatal(err) diff --git a/script/weblatedl.go b/script/weblatedl.go index 692cca11e..867ca9d2c 100644 --- a/script/weblatedl.go +++ b/script/weblatedl.go @@ -17,7 +17,7 @@ import ( "net/http" "os" "regexp" - "sort" + "slices" "strings" ) @@ -116,7 +116,7 @@ func reformatLanguageCode(origCode string) string { } func saveValidLangs(langs []string) { - sort.Strings(langs) + slices.Sort(langs) fd, err := os.Create("valid-langs.js") if err != nil { log.Fatal(err) From 98555a9a801765d7af1887cce7f4f6dccac01561 Mon Sep 17 00:00:00 2001 From: Luke Hamburg <1992842+luckman212@users.noreply.github.com> Date: Mon, 26 May 2025 07:43:38 -0400 Subject: [PATCH 4/5] fix(gui): update `uncamel()` to handle strings like 'IDs' (fixes #10128) (#10131) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > ⚠️ resubmission targeting `main` instead of `v2` ### Purpose Updates `uncamel()` function in [uncamelFilter.js](https://github.com/syncthing/syncthing/blob/v2/gui/default/syncthing/core/uncamelFilter.js) to fix camelCase conversion edge cases, see #10128 This adds an array called `reservedStrings` which will be printed as-is, e.g. `IDs`, `LAN` etc. I pre-populated this with what I believe makes sense, but of course this is easily updated. ### Testing I compiled all the config variables I could find in `syncthing/lib/config/*configuration.go` and tested this new function against them. Everything seemed to pass. ### Screenshot ![Image](https://github.com/user-attachments/assets/af8c9821-58b3-4a6a-8462-bead8a6d845a) --- gui/default/syncthing/core/uncamelFilter.js | 52 +++++++++++++-------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/gui/default/syncthing/core/uncamelFilter.js b/gui/default/syncthing/core/uncamelFilter.js index 269a42e90..97689f140 100644 --- a/gui/default/syncthing/core/uncamelFilter.js +++ b/gui/default/syncthing/core/uncamelFilter.js @@ -1,27 +1,39 @@ angular.module('syncthing.core') .filter('uncamel', function () { + const reservedStrings = [ + 'IDs', 'ID', // substrings must come AFTER longer keywords containing them + 'URL', 'UR', + 'API', 'QUIC', 'TCP', 'UDP', 'NAT', 'LAN', 'WAN', + 'KiB', 'MiB', 'GiB', 'TiB' + ]; return function (input) { - input = input.replace(/(.)([A-Z][a-z]+)/g, '$1 $2').replace(/([a-z0-9])([A-Z])/g, '$1 $2'); - var parts = input.split(' '); - var lastPart = parts.splice(-1)[0]; + if (!input || typeof input !== 'string') return ''; + const placeholders = {}; + let counter = 0; + reservedStrings.forEach(word => { + const placeholder = `__RSV${counter}__`; + const re = new RegExp(word, 'g'); + input = input.replace(re, placeholder); + placeholders[placeholder] = word; + counter++; + }); + input = input.replace(/([a-z0-9])([A-Z])/g, '$1 $2'); + Object.entries(placeholders).forEach(([ph, word]) => { + input = input.replace(new RegExp(ph, 'g'), ` ${word} `); + }); + let parts = input.split(' '); + const lastPart = parts.pop(); switch (lastPart) { - case "S": - parts.push('(seconds)'); - break; - case "M": - parts.push('(minutes)'); - break; - case "H": - parts.push('(hours)'); - break; - case "Ms": - parts.push('(milliseconds)'); - break; - default: - parts.push(lastPart); - break; + case 'S': parts.push('(seconds)'); break; + case 'M': parts.push('(minutes)'); break; + case 'H': parts.push('(hours)'); break; + case 'Ms': parts.push('(milliseconds)'); break; + default: parts.push(lastPart); break; } - input = parts.join(' '); - return input.charAt(0).toUpperCase() + input.slice(1); + parts = parts.map(part => { + const match = reservedStrings.find(w => w.toUpperCase() === part.toUpperCase()); + return match || part.charAt(0).toUpperCase() + part.slice(1); + }); + return parts.join(' ').replace(/\s+/g, ' ').trim(); }; }); From cade79019889933903a58cc8371af38e62da609a Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Mon, 26 May 2025 14:06:44 +0200 Subject: [PATCH 5/5] build: use specific token for pushing release tags --- .github/workflows/release-syncthing.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-syncthing.yaml b/.github/workflows/release-syncthing.yaml index 209a64d54..2dfd30164 100644 --- a/.github/workflows/release-syncthing.yaml +++ b/.github/workflows/release-syncthing.yaml @@ -13,11 +13,13 @@ jobs: create-release-tag: name: Create release tag runs-on: ubuntu-latest + environment: release steps: - uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882 + token: ${{ secrets.STRELEASE_GITHUB_TOKEN }} - uses: actions/setup-go@v5 with: @@ -45,11 +47,11 @@ jobs: run: | go run ./script/relnotes.go --new-ver "$NEXT" --branch "$GITHUB_REF_NAME" --prev-ver "$PREV" > notes.md env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.STRELEASE_GITHUB_TOKEN }} - name: Create and push tag run: | git config --global user.name 'Syncthing Release Automation' git config --global user.email 'release@syncthing.net' - git tag -a -F notes.md "$NEXT" + git tag -a -F notes.md --cleanup=whitespace "$NEXT" git push origin "$NEXT"