--- /dev/null
+// MsgSyncReq: run triggers for changed files
+
+// Copyright (C) 2021 Simon Ruderich
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package sync
+
+import (
+ "path/filepath"
+ "strings"
+
+ "ruderich.org/simon/safcm"
+)
+
+// queueTriggers queues all triggers applying to file.
+func (s *Sync) queueTriggers(file *safcm.File) {
+ for _, path := range triggerPaths(file.Path) {
+ if s.req.Files[path].TriggerCommands == nil {
+ continue
+ }
+ // Queue each trigger only once
+ if s.triggersActive[path] {
+ s.log.Debugf(
+ "files: %q: skipping trigger on %q, already active",
+ file.Path, path)
+ continue
+ }
+
+ s.log.Verbosef("files: %q: queuing trigger on %q",
+ file.Path, path)
+ s.triggers = append(s.triggers, path)
+ s.triggersActive[path] = true
+ }
+}
+
+// triggerPaths returns all possible trigger paths for path, that is the path
+// itself and all parent paths. The paths are returned in reverse order so
+// more specific triggers can override effects of less specific ones (first
+// "/" or ".", then the parents and finally path itself).
+func triggerPaths(path string) []string {
+ sep := string(filepath.Separator)
+ if path == sep {
+ return []string{path}
+ } else if path == "." {
+ return []string{path}
+ }
+ parts := strings.Split(path, sep)
+ if strings.HasPrefix(path, sep) {
+ // Absolute path
+ parts[0] = sep
+ } else {
+ // Relative path
+ parts = append([]string{"."}, parts...)
+ }
+
+ var res []string
+ for i := 0; i < len(parts); i++ {
+ res = append(res, filepath.Join(parts[:i+1]...))
+ }
+ return res
+}