Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9260248543 | ||
|
|
c4a348db67 | ||
|
|
e125f8b05b | ||
|
|
fb198a0645 | ||
|
|
506181599c | ||
|
|
15d0bdcba9 | ||
|
|
b6b0d0664d | ||
|
|
baa3aa4bad | ||
|
|
a48a31e3f5 |
@@ -130,4 +130,5 @@ Vil Brekin (Vilbrekin) <vilbrekin@gmail.com>
|
||||
William A. Kennington III (wkennington) <william@wkennington.com>
|
||||
Wulf Weich (wweich) <wweich@users.noreply.github.com> <wweich@gmx.de> <wulf@weich-kr.de>
|
||||
Xavier O. (damajor) <damajor@gmail.com>
|
||||
xjtdy888 (xjtdy888) <xjtdy888@163.com>
|
||||
Yannic A. (eipiminus1) <eipiminusone+github@gmail.com> <eipiminus1@users.noreply.github.com>
|
||||
|
||||
@@ -251,6 +251,8 @@ func handleMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func handleAssets(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Cache-Control", "no-cache, must-revalidate")
|
||||
|
||||
assets := auto.Assets()
|
||||
path := r.URL.Path[1:]
|
||||
if path == "" {
|
||||
@@ -263,11 +265,28 @@ func handleAssets(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
etag := fmt.Sprintf("%d", auto.Generated)
|
||||
modified := time.Unix(auto.Generated, 0).UTC()
|
||||
|
||||
w.Header().Set("Last-Modified", modified.Format(http.TimeFormat))
|
||||
w.Header().Set("Etag", etag)
|
||||
|
||||
mtype := mimeTypeForFile(path)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
|
||||
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modified.Add(time.Second).After(t) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
if match := r.Header.Get("If-None-Match"); match != "" {
|
||||
if strings.Contains(match, etag) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
}
|
||||
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
} else {
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/auto"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
@@ -71,6 +72,8 @@ func (s *staticsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (s *staticsServer) serveAsset(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Cache-Control", "no-cache, must-revalidate")
|
||||
|
||||
file := r.URL.Path
|
||||
|
||||
if file[0] == '/' {
|
||||
@@ -122,6 +125,24 @@ func (s *staticsServer) serveAsset(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
etag := fmt.Sprintf("%d", auto.Generated)
|
||||
modified := time.Unix(auto.Generated, 0).UTC()
|
||||
|
||||
w.Header().Set("Last-Modified", modified.Format(http.TimeFormat))
|
||||
w.Header().Set("Etag", etag)
|
||||
|
||||
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modified.Add(time.Second).After(t) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
|
||||
if match := r.Header.Get("If-None-Match"); match != "" {
|
||||
if strings.Contains(match, etag) {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
mtype := s.mimeTypeForFile(file)
|
||||
if len(mtype) != 0 {
|
||||
w.Header().Set("Content-Type", mtype)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"Add Remote Device": "Ajouter un appareil...",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "ATTENTION !!! Lui permettre d'ajouter et enlever des membres à toutes mes listes de membres des partages dont il fait (ou fera !) partie (ceci permet de créer automatiquement toutes les liaisons point à point possibles en complétant mes listes par les siennes, meilleur débit de réception par cumul des débits d'envoi, indépendance vis à vis de l'introducteur, etc).",
|
||||
"Add new folder?": "Ajouter ce partage ?",
|
||||
"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.": "De plus, l'intervalle de réanalyse complète sera augmenté (60 fois, c.-à-d. une nouvelle valeur par défaut de 1h). Vous pouvez également la configurer manuellement plus tard, pour chaque partage, après avoir choisi Non.",
|
||||
"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.": "Dans ce cas, l'intervalle de réanalyse complète sera augmenté (60 fois, c.-à-d. une nouvelle valeur par défaut de 1h). Vous pouvez également la configurer manuellement plus tard, pour chaque partage, après avoir choisi Non.",
|
||||
"Address": "Adresse",
|
||||
"Addresses": "Adresses",
|
||||
"Advanced": "Avancé",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"Add Remote Device": "다른 기기 추가",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "상호 공유 폴더에 대해 유도자의 장치를 장치 목록에 추가합니다.",
|
||||
"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.": "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.",
|
||||
"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": "고급",
|
||||
@@ -50,7 +50,7 @@
|
||||
"Connection Error": "연결 에러",
|
||||
"Connection Type": "연결 종류",
|
||||
"Connections": "연결",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Syncthing는 변경 사항을 지속적으로 감지 할 수 있습니다. 이렇게 하면 디스크의 변경 사항을 감지하고 수정 된 경로에서만 검사를 실행합니다. 이점은 변경 사항이 더 빠르게 전파되고 전체 탐색 횟수가 줄어듭니다.",
|
||||
"Copied from elsewhere": "다른 곳에서 복사됨",
|
||||
"Copied from original": "원본에서 복사됨",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 the following Contributors:",
|
||||
@@ -77,7 +77,7 @@
|
||||
"Discovery Failures": "탐색 실패",
|
||||
"Do not restore": "복구 하지 않기",
|
||||
"Do not restore all": "모두 복구 하지 않기",
|
||||
"Do you want to enable watching for changes for all your folders?": "Do you want to enable watching for changes for all your folders?",
|
||||
"Do you want to enable watching for changes for all your folders?": "변경 사항 감시를 당신의 모든 폴더에서 활성화 하는걸 원하시나요?",
|
||||
"Documentation": "문서",
|
||||
"Download Rate": "다운로드 속도",
|
||||
"Downloaded": "다운로드됨",
|
||||
@@ -117,7 +117,7 @@
|
||||
"Folder Path": "폴더 경로",
|
||||
"Folder Type": "폴더 유형",
|
||||
"Folders": "폴더",
|
||||
"Full Rescan Interval (s)": "모두 재 탐색 간격 (s)",
|
||||
"Full Rescan Interval (s)": "전체 탐색 간격 (s)",
|
||||
"GUI": "GUI",
|
||||
"GUI Authentication Password": "GUI 인증 비밀번호",
|
||||
"GUI Authentication User": "GUI 인증 사용자",
|
||||
@@ -333,9 +333,9 @@
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "경고, 이 경로는 현재 존재하는 폴더 \"{{otherFolderLabel}}\" ({{otherFolder}}) 의 상위 폴더 입니다.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "경고, 이 경로는 현재 존재하는 폴더 \"{{otherFolder}}\" 의 하위 폴더 입니다.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "경고, 이 경로는 현재 존재하는 폴더 \"{{otherFolderLabel}}\" ({{otherFolder}}) 의 하위 폴더 입니다.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Warning: If you are using an external watcher like {{syncthingInotify}}, you should make sure it is deactivated.",
|
||||
"Watch for Changes": "Watch for Changes",
|
||||
"Watching for Changes": "Watching for Changes",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "경고 : {{syncthingInotify}} 와 같은 외부 감시 도구를 사용하는 경우 비활성화되어 있는지 확인해야 합니다.",
|
||||
"Watch for Changes": "변경 사항 감시",
|
||||
"Watching for Changes": "변경 사항 감시",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "새 장치를 추가할 시 추가한 기기 쪽에서도 이 장치를 추가해야 합니다.",
|
||||
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "새 폴더를 추가할 시 폴더 ID는 장치간에 폴더를 묶을 때 사용됩니다. 대소문자를 구분하며 모든 장치에서 같은 ID를 사용해야 합니다.",
|
||||
"Yes": "예",
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
"Mod. Device": "Dispositivo mod.",
|
||||
"Mod. Time": "Quando foi mod.",
|
||||
"Move to top of queue": "Mover para o topo da fila",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Caractere polivalente multi-nível (faz corresponder a vários níveis de pastas)",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Símbolo polivalente multi-nível (faz corresponder a vários níveis de pastas)",
|
||||
"Never": "Nunca",
|
||||
"New Device": "Novo dispositivo",
|
||||
"New Folder": "Nova pasta",
|
||||
@@ -187,7 +187,7 @@
|
||||
"Outgoing Rate Limit (KiB/s)": "Limite da velocidade de envio (KiB/s)",
|
||||
"Override Changes": "Sobrepor alterações",
|
||||
"Path": "Caminho",
|
||||
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Caminho para a pasta no computador local. Será criada, caso não exista. O caractere (~) pode ser utilizado como atalho para",
|
||||
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Caminho para a pasta no computador local. Será criada, caso não exista. O til (~) pode ser utilizado como atalho para",
|
||||
"Path where new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {%tilde%}.": "Caminho no qual as novas pastas aceites automaticamente serão criadas, assim como o caminho predefinido sugerido ao adicionar novas pastas através da interface do utilizador. O til (~) expande para {{tilde}}.",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Caminho da pasta onde as versões deverão ser guardadas (deixe vazio para ficar a pasta predefinida .stversions dentro da pasta partilhada).",
|
||||
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Caminho onde as versões são guardadas (deixe vazio para usar a pasta predefinida .stversions dentro da pasta a que se refere).",
|
||||
@@ -220,7 +220,7 @@
|
||||
"Rescan": "Verificar agora",
|
||||
"Rescan All": "Verificar todas agora",
|
||||
"Rescan Interval": "Intervalo entre verificações",
|
||||
"Rescans": "Verificação de alterações",
|
||||
"Rescans": "Verificações",
|
||||
"Restart": "Reiniciar",
|
||||
"Restart Needed": "É preciso reiniciar",
|
||||
"Restarting": "Reiniciando",
|
||||
@@ -232,7 +232,7 @@
|
||||
"Running": "Em execução",
|
||||
"Save": "Gravar",
|
||||
"Scan Time Remaining": "Tempo restante da verificação",
|
||||
"Scanning": "Verificando",
|
||||
"Scanning": "Verificação de alterações",
|
||||
"See external versioner help for supported templated command line parameters.": "Veja a ajuda do gestor de versões externo para saber que parâmetros da linha de comandos são suportados.",
|
||||
"See external versioning help for supported templated command line parameters.": "Veja a ajuda externa sobre gestão de versões para ver os modelos suportados de parâmetros para a linha de comandos.",
|
||||
"Select a version": "Seleccione uma versão",
|
||||
@@ -257,7 +257,7 @@
|
||||
"Shutdown": "Desligar",
|
||||
"Shutdown Complete": "Encerramento completado",
|
||||
"Simple File Versioning": "Simples",
|
||||
"Single level wildcard (matches within a directory only)": "Caractere polivalente de um só nível (faz corresponder apenas dentro de uma pasta)",
|
||||
"Single level wildcard (matches within a directory only)": "Símbolo polivalente de um só nível (faz corresponder apenas dentro de uma pasta)",
|
||||
"Size": "Tamanho",
|
||||
"Smallest First": "Primeiro os menores",
|
||||
"Some items could not be restored:": "Não foi possível restaurar alguns dos itens:",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<p translate>Copyright © 2014-2017 the following Contributors:</p>
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="contributor-list">
|
||||
Jakob Borg, Audrius Butkevicius, Simon Frei, Alexander Graf, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, Aaron Bieber, Adam Piggott, Adel Qalieh, Alessandro G., Alexandre Viau, Andrew Dunham, Andrey D, Antoine Lamielle, Arthur Axel fREW Schmidt, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benny Ng, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Colin Kennedy, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Dominik Heidler, Elias Jarlebring, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Graham Miln, Harrison Jones, Heiko Zuerker, Jaakko Hannikainen, Jacek Szafarkiewicz, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jochen Voss, Johan Vromans, John Rinehart, Jose Manuel Delicado, Karol Różycki, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Mark Pulford, Mateusz Naściszewski, Matt Burke, Max Schulze, Michael Jephcote, Michael Tilli, Nicholas Rishel, Niels Peter Roest, Nils Jakobi, Pascal Jungblut, Pawel Palenica, Peter Hoeg, Peter Marquardt, Phill Luby, Piotr Bejda, Pramodh KP, Robert Carosi, Roman Zaynetdinov, Ross Smith II, Sacheendra Talluri, Scott Klupfel, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Tim Abell, Tim Howes, Tobias Nygren, Tobias Tom, Tomas Cerveny, Tully Robinson, Tyler Brazier, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, William A. Kennington III, Xavier O., Yannic A.
|
||||
Jakob Borg, Audrius Butkevicius, Simon Frei, Alexander Graf, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, Aaron Bieber, Adam Piggott, Adel Qalieh, Alessandro G., Alexandre Viau, Andrew Dunham, Andrey D, Antoine Lamielle, Arthur Axel fREW Schmidt, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benny Ng, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Colin Kennedy, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Dominik Heidler, Elias Jarlebring, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Graham Miln, Harrison Jones, Heiko Zuerker, Jaakko Hannikainen, Jacek Szafarkiewicz, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jochen Voss, Johan Vromans, John Rinehart, Jose Manuel Delicado, Karol Różycki, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Mark Pulford, Mateusz Naściszewski, Matt Burke, Max Schulze, Michael Jephcote, Michael Tilli, Nicholas Rishel, Niels Peter Roest, Nils Jakobi, Pascal Jungblut, Pawel Palenica, Peter Hoeg, Peter Marquardt, Phill Luby, Piotr Bejda, Pramodh KP, Robert Carosi, Roman Zaynetdinov, Ross Smith II, Sacheendra Talluri, Scott Klupfel, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Tim Abell, Tim Howes, Tobias Nygren, Tobias Tom, Tomas Cerveny, Tully Robinson, Tyler Brazier, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, William A. Kennington III, Xavier O., Yannic A., xjtdy888
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
@@ -2,20 +2,13 @@ angular.module('syncthing.core')
|
||||
.directive('notification', function () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: true,
|
||||
scope: {},
|
||||
transclude: true,
|
||||
template: '<div class="row" ng-if="visible()"><div class="col-md-12" ng-transclude></div></div>',
|
||||
link: function (scope, elm, attrs) {
|
||||
scope.visible = function () {
|
||||
return scope.config.options.unackedNotificationIDs.indexOf(attrs.id) > -1;
|
||||
}
|
||||
scope.dismiss = function () {
|
||||
var idx = scope.config.options.unackedNotificationIDs.indexOf(attrs.id);
|
||||
if (idx > -1) {
|
||||
scope.config.options.unackedNotificationIDs.splice(idx, 1);
|
||||
scope.saveConfig();
|
||||
}
|
||||
}
|
||||
return scope.$parent.config.options.unackedNotificationIDs.indexOf(attrs.id) > -1;
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<p translate>This is an example notification. ID of the notification should be appended to Options.UnackedNotificationIDs of the config.</p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="btn btn-sm btn-default pull-right" ng-click="dismiss()">
|
||||
<button type="button" class="btn btn-sm btn-default pull-right" ng-click="dismissNotification('exampleNotification')">
|
||||
<span class="fa fa-check"></span> <span translate>OK</span>
|
||||
</button>
|
||||
<div class="clearfix"></div>
|
||||
@@ -31,10 +31,10 @@
|
||||
<p><a href="https://docs.syncthing.net/users/releases.html"><span class="fa fa-fw fa-book"></span> <span translate>Learn more</span></a></p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="btn btn-sm btn-default pull-right" ng-click="editSettings()">
|
||||
<button type="button" class="btn btn-sm btn-default pull-right" ng-click="editSettings(); dismissNotification('channelNotification')">
|
||||
<span class="fa fa-cog"></span> <span translate>Settings</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="dismiss()">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="dismissNotification('channelNotification')">
|
||||
<span class="fa fa-check"></span> <span translate>OK</span>
|
||||
</button>
|
||||
<div class="clearfix"></div>
|
||||
@@ -58,10 +58,10 @@
|
||||
</div>
|
||||
<div class="panel-footer clearfix">
|
||||
<div class="pull-right">
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-click="activateAllFsWatchers(); dismiss()">
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-click="activateAllFsWatchers(); dismissNotification('fsWatcherNotification')">
|
||||
<span class="fa fa-check"></span> <span translate>Yes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="dismiss()">
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="dismissNotification('fsWatcherNotification')">
|
||||
<span class="fa fa-times"></span> <span translate>No</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1699,6 +1699,7 @@ angular.module('syncthing.core')
|
||||
delete folderCfg.versioning;
|
||||
}
|
||||
|
||||
var ignoresLoaded = !$('#folder-ignores textarea').is(':disabled');
|
||||
var ignores = $('#folder-ignores textarea').val().split('\n');
|
||||
// Split always returns a minimum 1-length array even for no patterns
|
||||
if (ignores.length === 1 && ignores[0] === "") {
|
||||
@@ -1711,7 +1712,7 @@ angular.module('syncthing.core')
|
||||
$scope.folders[folderCfg.id] = folderCfg;
|
||||
$scope.config.folders = folderList($scope.folders);
|
||||
|
||||
if ($scope.editingExisting && ignores !== folderCfg.ignores) {
|
||||
if (ignoresLoaded && $scope.editingExisting && ignores !== folderCfg.ignores) {
|
||||
saveIgnores(ignores);
|
||||
};
|
||||
|
||||
@@ -2246,4 +2247,12 @@ angular.module('syncthing.core')
|
||||
$scope.sizeOf = function (dict) {
|
||||
return Object.keys(dict).length;
|
||||
};
|
||||
|
||||
$scope.dismissNotification = function (id) {
|
||||
var idx = $scope.config.options.unackedNotificationIDs.indexOf(id);
|
||||
if (idx > -1) {
|
||||
$scope.config.options.unackedNotificationIDs.splice(idx, 1);
|
||||
$scope.saveConfig();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<td ng-if="!changeEvent.data.modifiedBy"><span translate>Unknown</span></td>
|
||||
<td>{{changeEvent.data.action}}</td>
|
||||
<td>{{changeEvent.data.type}}</td>
|
||||
<td class="no-overflow-ellipse">{{changeEvent.data.label}}</td>
|
||||
<td class="no-overflow-ellipse">{{folderLabel(changeEvent.data.folder)}}</td>
|
||||
<td class="no-overflow-ellipse">{{changeEvent.data.path}}</td>
|
||||
<td class="no-overflow-ellipse">{{changeEvent.time | date:"yyyy-MM-dd HH:mm:ss"}}</td>
|
||||
</tr>
|
||||
|
||||
@@ -539,6 +539,14 @@ func (db *Instance) dropFolder(folder []byte) {
|
||||
}
|
||||
dbi.Release()
|
||||
|
||||
// Remove all sequences related to the folder
|
||||
sequenceKey := db.sequenceKey([]byte(folder), 0)
|
||||
dbi = t.NewIterator(util.BytesPrefix(sequenceKey[:keyPrefixLen+keyFolderLen]), nil)
|
||||
for dbi.Next() {
|
||||
db.Delete(dbi.Key(), nil)
|
||||
}
|
||||
dbi.Release()
|
||||
|
||||
// Remove all items related to the given folder from the global bucket
|
||||
dbi = t.NewIterator(util.BytesPrefix([]byte{KeyTypeGlobal}), nil)
|
||||
for dbi.Next() {
|
||||
|
||||
+13
-2
@@ -140,9 +140,14 @@ func (m *Matcher) Load(file string) error {
|
||||
defer fd.Close()
|
||||
|
||||
m.changeDetector.Reset()
|
||||
m.changeDetector.Remember(m.fs, file, info.ModTime())
|
||||
|
||||
return m.parseLocked(fd, file)
|
||||
err = m.parseLocked(fd, file)
|
||||
// If we failed to parse, don't cache, as next time Load is called
|
||||
// we'll pretend it's all good.
|
||||
if err == nil {
|
||||
m.changeDetector.Remember(m.fs, file, info.ModTime())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Matcher) Parse(r io.Reader, file string) error {
|
||||
@@ -445,6 +450,12 @@ func parseIgnoreFile(fs fs.Filesystem, fd io.Reader, currentFile string, cd Chan
|
||||
var includePatterns []Pattern
|
||||
if includePatterns, err = loadParseIncludeFile(fs, includeFile, cd, linesSeen); err == nil {
|
||||
patterns = append(patterns, includePatterns...)
|
||||
} else {
|
||||
// Wrap the error, as if the include does not exist, we get a
|
||||
// IsNotExists(err) == true error, which we use to check
|
||||
// existance of the .stignore file, and just end up assuming
|
||||
// there is none, rather than a broken include.
|
||||
err = fmt.Errorf("failed to load include file %s: %s", includeFile, err.Error())
|
||||
}
|
||||
case strings.HasSuffix(line, "/**"):
|
||||
err = addPattern(line)
|
||||
|
||||
@@ -981,3 +981,42 @@ func TestIssue4689(t *testing.T) {
|
||||
t.Fatalf("wrong lines parsing changed comment:\n%v", lines)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue4901(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
stignore := `
|
||||
#include unicorn-lazor-death
|
||||
puppy
|
||||
`
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, ".stignore"), []byte(stignore), 0777); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
pats := New(fs.NewFilesystem(fs.FilesystemTypeBasic, dir), WithCache(true))
|
||||
// Cache does not suddenly make the load succeed.
|
||||
for i := 0; i < 2; i++ {
|
||||
err := pats.Load(".stignore")
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
}
|
||||
if fs.IsNotExist(err) {
|
||||
t.Fatalf("unexpected error type")
|
||||
}
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, "unicorn-lazor-death"), []byte(" "), 0777); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
err = pats.Load(".stignore")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1490,11 +1490,10 @@ func (m *Model) GetIgnores(folder string) ([]string, []string, error) {
|
||||
}
|
||||
|
||||
ignores, ok := m.folderIgnores[folder]
|
||||
if ok {
|
||||
return ignores.Lines(), ignores.Patterns(), nil
|
||||
if !ok {
|
||||
ignores = ignore.New(fs.NewFilesystem(cfg.FilesystemType, cfg.Path))
|
||||
}
|
||||
|
||||
ignores = ignore.New(fs.NewFilesystem(cfg.FilesystemType, cfg.Path))
|
||||
if err := ignores.Load(".stignore"); err != nil && !fs.IsNotExist(err) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "STDISCOSRV" "1" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "STDISCOSRV" "1" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
stdiscosrv \- Syncthing Discovery Server
|
||||
.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "STRELAYSRV" "1" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "STRELAYSRV" "1" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
strelaysrv \- Syncthing Relay Server
|
||||
.
|
||||
|
||||
+93
-7
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-BEP" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-BEP" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-bep \- Block Exchange Protocol v1
|
||||
.
|
||||
@@ -41,8 +41,10 @@ forms the \fIglobal model\fP\&. Each device strives to get its folders in sync
|
||||
with the global model by requesting missing or outdated blocks from the
|
||||
other devices in the cluster.
|
||||
.sp
|
||||
File data is described and transferred in units of \fIblocks\fP, each being
|
||||
128 KiB (131072 bytes) in size.
|
||||
File data is described and transferred in units of \fIblocks\fP, each being from
|
||||
128 KiB (131072 bytes) to 16 MiB in size, in steps of powers of two. The
|
||||
block size may vary between files but is constant in any given file, except
|
||||
for the last block which may be smaller.
|
||||
.sp
|
||||
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
|
||||
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this
|
||||
@@ -421,7 +423,8 @@ message FileInfo {
|
||||
bool invalid = 7;
|
||||
bool no_permissions = 8;
|
||||
Vector version = 9;
|
||||
int64 sequence = 10;
|
||||
int64 sequence = 10;
|
||||
int32 block_size = 13;
|
||||
|
||||
repeated BlockInfo Blocks = 16;
|
||||
string symlink_target = 17;
|
||||
@@ -513,10 +516,16 @@ The \fBsequence\fP field is the value of a device local monotonic clock at the
|
||||
time of last local database update to a file. The clock ticks on every local
|
||||
database update, thus forming a sequence number over database updates.
|
||||
.sp
|
||||
The \fBblock_size\fP field is the size, in bytes, of each individual block in
|
||||
the block list (except, possibly, the last block). If this field is missing
|
||||
or zero, the block size is assumed to be 128 KiB (131072 bytes). Valid
|
||||
values of this field are the powers of two from 128 KiB through 16 MiB. See
|
||||
also \fI\%Selection of Block Size\fP\&.
|
||||
.sp
|
||||
The \fBblocks\fP list contains the size and hash for each block in the file.
|
||||
Each block represents a 128 KiB slice of the file, except for the last block
|
||||
which may represent a smaller amount of data. The block list is empty for
|
||||
directories and symlinks.
|
||||
Each block represents a \fBblock_size\fP\-sized slice of the file, except for
|
||||
the last block which may represent a smaller amount of data. The block list
|
||||
is empty for directories and symlinks.
|
||||
.sp
|
||||
The \fBsymlink_target\fP field contains the symlink target, for entries of
|
||||
symlink type. It is empty for all other entry types.
|
||||
@@ -839,6 +848,83 @@ a connection close. This size was chosen to accommodate Index messages
|
||||
containing a large block list. It’s intended that the limit may be further
|
||||
reduced in a future protocol update supporting variable block sizes (and
|
||||
thus shorter block lists for large files).
|
||||
.SH SELECTION OF BLOCK SIZE
|
||||
.sp
|
||||
The desired block size for any given file is the smallest block size that
|
||||
results in fewer than 2000 blocks, or the maximum block size for larger
|
||||
files. This rule results in the following table of block sizes per file
|
||||
size:
|
||||
.TS
|
||||
center;
|
||||
|l|l|.
|
||||
_
|
||||
T{
|
||||
File Size
|
||||
T} T{
|
||||
Block Size
|
||||
T}
|
||||
_
|
||||
T{
|
||||
0 \- 250 MiB
|
||||
T} T{
|
||||
128 KiB
|
||||
T}
|
||||
_
|
||||
T{
|
||||
250 MiB \- 500 MiB
|
||||
T} T{
|
||||
256 KiB
|
||||
T}
|
||||
_
|
||||
T{
|
||||
500 MiB \- 1 GiB
|
||||
T} T{
|
||||
512 KiB
|
||||
T}
|
||||
_
|
||||
T{
|
||||
1 GiB \- 2 GiB
|
||||
T} T{
|
||||
1 MiB
|
||||
T}
|
||||
_
|
||||
T{
|
||||
2 GiB \- 4 GiB
|
||||
T} T{
|
||||
2 MiB
|
||||
T}
|
||||
_
|
||||
T{
|
||||
4 GiB \- 8 GiB
|
||||
T} T{
|
||||
4 MiB
|
||||
T}
|
||||
_
|
||||
T{
|
||||
8 GiB \- 16 GiB
|
||||
T} T{
|
||||
8 MiB
|
||||
T}
|
||||
_
|
||||
T{
|
||||
16 GiB \- up
|
||||
T} T{
|
||||
16 MiB
|
||||
T}
|
||||
_
|
||||
.TE
|
||||
.sp
|
||||
An implementation MAY deviate from the block size rule when there is good
|
||||
reason to do so. For example, if a file has been indexed at a certain block
|
||||
size and grows beyond 2000 blocks it may be retained at the current block
|
||||
size for practical reasons. When there is no overriding reason to the
|
||||
contrary, such as when indexing a new file for the first time, the block
|
||||
size rule above SHOULD be followed.
|
||||
.sp
|
||||
An implementation MUST therefore accept files with a block size differing
|
||||
from the above rule. This does not mean that arbitrary block sizes are
|
||||
allowed. The block size used MUST be exactly one of the power\-of\-two block
|
||||
sizes listed in the table above.
|
||||
.SH EXAMPLE EXCHANGE
|
||||
.TS
|
||||
center;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-CONFIG" "5" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-CONFIG" "5" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-config \- Syncthing Configuration
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-DEVICE-IDS" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-DEVICE-IDS" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-device-ids \- Understanding Device IDs
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-EVENT-API" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-EVENT-API" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-event-api \- Event API
|
||||
.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-FAQ" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-FAQ" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-faq \- Frequently Asked Questions
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-GLOBALDISCO" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-GLOBALDISCO" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-globaldisco \- Global Discovery Protocol v3
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-LOCALDISCO" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-LOCALDISCO" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-localdisco \- Local Discovery Protocol v4
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-NETWORKING" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-NETWORKING" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-networking \- Firewall Setup
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-RELAY" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-RELAY" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-relay \- Relay Protocol v1
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-REST-API" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-REST-API" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-rest-api \- REST API
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-SECURITY" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-SECURITY" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-security \- Security Principles
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-STIGNORE" "5" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-STIGNORE" "5" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-stignore \- Prevent files from being synchronized to other nodes
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING-VERSIONING" "7" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING-VERSIONING" "7" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-versioning \- Keep automatic backups of deleted files by other nodes
|
||||
.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SYNCTHING" "1" "Apr 18, 2018" "v0.14" "Syncthing"
|
||||
.TH "SYNCTHING" "1" "May 05, 2018" "v0.14" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing \- Syncthing
|
||||
.
|
||||
|
||||
+7
-2
@@ -19,10 +19,13 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
var tpl = template.Must(template.New("assets").Parse(`package auto
|
||||
|
||||
const Generated int64 = {{.Generated}}
|
||||
|
||||
func Assets() map[string][]byte {
|
||||
var assets = make(map[string][]byte, {{.Assets | len}})
|
||||
{{range $asset := .Assets}}
|
||||
@@ -75,7 +78,8 @@ func walkerFor(basePath string) filepath.WalkFunc {
|
||||
}
|
||||
|
||||
type templateVars struct {
|
||||
Assets []asset
|
||||
Assets []asset
|
||||
Generated int64
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -84,7 +88,8 @@ func main() {
|
||||
filepath.Walk(flag.Arg(0), walkerFor(flag.Arg(0)))
|
||||
var buf bytes.Buffer
|
||||
tpl.Execute(&buf, templateVars{
|
||||
Assets: assets,
|
||||
Assets: assets,
|
||||
Generated: time.Now().Unix(),
|
||||
})
|
||||
bs, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user