]> ruderich.org/simon Gitweb - safcm/safcm.git/blobdiff - cmd/safcm/sync_changes.go
changes: display "no changes" when nothing was changed
[safcm/safcm.git] / cmd / safcm / sync_changes.go
index 14d73c271a4bb0d8434d5896bf17bd78a4552407..3e91768bfca3eb3273e5c24954c506f86934a63b 100644 (file)
@@ -30,6 +30,40 @@ import (
 // the remote helper is untrusted and must be either escaped with %q or by
 // calling EscapeControlCharacters().
 
+func (s *Sync) formatChanges(resp safcm.MsgSyncResp) string {
+       var changes []string
+       if len(resp.FileChanges) > 0 {
+               changes = append(changes,
+                       s.formatFileChanges(resp.FileChanges))
+       }
+       if len(resp.PackageChanges) > 0 {
+               changes = append(changes,
+                       s.formatPackageChanges(resp.PackageChanges))
+       }
+       if len(resp.ServiceChanges) > 0 {
+               changes = append(changes,
+                       s.formatServiceChanges(resp.ServiceChanges))
+       }
+       if len(resp.CommandChanges) > 0 {
+               changes = append(changes,
+                       s.formatCommandChanges(resp.CommandChanges))
+       }
+       if len(changes) == 0 {
+               // Notify user that the host was synced successfully
+               return "no changes"
+       }
+
+       x := strings.Join(changes, "\n")
+       // If quiet is used and only commands without output were executed
+       // then don't prepend a newline so that the whole change output of a
+       // host fits in a single line. This makes the output much more
+       // readable with multiple hosts.
+       if strings.Count(x, "\n") == 1 {
+               return x
+       }
+       return "\n" + x
+}
+
 func (s *Sync) formatFileChanges(changes []safcm.FileChange) string {
        var buf strings.Builder
        fmt.Fprintf(&buf, "changed %d file(s):", len(changes))
@@ -145,13 +179,41 @@ func (s *Sync) formatServiceChanges(changes []safcm.ServiceChange) string {
 func (s *Sync) formatCommandChanges(changes []safcm.CommandChange) string {
        const indent = "   > "
 
+       // Quiet hides all successful, non-trigger commands which produce no
+       // output. This is useful as many commands will be used to enforce a
+       // certain state (e.g. file not-present, `ainsl`, etc.) and are run on
+       // each sync. Displaying them provides not much useful information.
+       // Instead, quiet shows them only when they produce output (e.g.
+       // `ainsl`, `rm -v`) and thus modify the host's state.
+       var noOutput int
+       if s.config.Quiet {
+               for _, x := range changes {
+                       if x.Trigger == "" &&
+                               x.Error == "" &&
+                               x.Output == "" {
+                               noOutput++
+                       }
+               }
+       }
+
        var buf strings.Builder
-       fmt.Fprintf(&buf, "executed %d command(s):", len(changes))
+       fmt.Fprintf(&buf, "executed %d command(s)", len(changes))
+       if noOutput > 0 && !s.config.DryRun {
+               fmt.Fprintf(&buf, ", %d with no output", noOutput)
+       }
+       if noOutput != len(changes) {
+               fmt.Fprintf(&buf, ":")
+       }
        if s.config.DryRun {
                fmt.Fprintf(&buf, " (dry-run)")
        }
        fmt.Fprintf(&buf, "\n")
        for _, x := range changes {
+               if noOutput > 0 &&
+                       x.Trigger == "" && x.Error == "" && x.Output == "" {
+                       continue
+               }
+
                fmt.Fprintf(&buf, "%s", s.formatTarget(x.Command))
                if x.Trigger != "" {
                        fmt.Fprintf(&buf, ", trigger for %q", x.Trigger)
@@ -198,10 +260,6 @@ func (s *Sync) formatDiff(diff string) string {
 }
 
 func indentBlock(x string, sep string) string {
-       if x == "" {
-               return ""
-       }
-
        lines := strings.Split(x, "\n")
        if lines[len(lines)-1] == "" {
                lines = lines[:len(lines)-1]