X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=cmd%2Fsafcm%2Fsync_changes.go;h=f597ae1a7fdc6b3532bbc1f15a22a3dae7ae2b4b;hb=8222dd7be72bef3773eb66b04af6094e584b13fb;hp=14d73c271a4bb0d8434d5896bf17bd78a4552407;hpb=f2f2bc47e8729548f3c10117f7f008b547c4afc5;p=safcm%2Fsafcm.git diff --git a/cmd/safcm/sync_changes.go b/cmd/safcm/sync_changes.go index 14d73c2..f597ae1 100644 --- a/cmd/safcm/sync_changes.go +++ b/cmd/safcm/sync_changes.go @@ -30,13 +30,48 @@ 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)) if s.config.DryRun { - fmt.Fprintf(&buf, " (dry-run)") + fmt.Fprintf(&buf, "will change %d file(s): (dry-run)\n", + len(changes)) + } else { + fmt.Fprintf(&buf, "changed %d file(s):\n", len(changes)) } - fmt.Fprintf(&buf, "\n") for _, x := range changes { fmt.Fprintf(&buf, "%s:", s.formatTarget(x.Path)) @@ -82,7 +117,6 @@ func (s *Sync) formatFileChanges(changes []safcm.FileChange) string { } fmt.Fprintf(&buf, "\n") } - return buf.String() } func formatFileType(info safcm.FileChangeInfo) string { @@ -108,11 +142,12 @@ func formatFilePerm(info safcm.FileChangeInfo) string { func (s *Sync) formatPackageChanges(changes []safcm.PackageChange) string { var buf strings.Builder - fmt.Fprintf(&buf, "installed %d package(s):", len(changes)) if s.config.DryRun { - fmt.Fprintf(&buf, " (dry-run)") + fmt.Fprintf(&buf, "will install %d package(s): (dry-run)\n", + len(changes)) + } else { + fmt.Fprintf(&buf, "installed %d package(s):\n", len(changes)) } - fmt.Fprintf(&buf, "\n") for _, x := range changes { // TODO: indicate if installation failed fmt.Fprintf(&buf, "%s\n", s.formatTarget(x.Name)) @@ -122,11 +157,12 @@ func (s *Sync) formatPackageChanges(changes []safcm.PackageChange) string { func (s *Sync) formatServiceChanges(changes []safcm.ServiceChange) string { var buf strings.Builder - fmt.Fprintf(&buf, "modified %d service(s):", len(changes)) if s.config.DryRun { - fmt.Fprintf(&buf, " (dry-run)") + fmt.Fprintf(&buf, "will modify %d service(s): (dry-run)\n", + len(changes)) + } else { + fmt.Fprintf(&buf, "modified %d service(s):\n", len(changes)) } - fmt.Fprintf(&buf, "\n") for _, x := range changes { var info []string if x.Started { @@ -145,13 +181,45 @@ 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)) + if s.config.DryRun { + fmt.Fprintf(&buf, "will execute %d command(s)", len(changes)) + } else { + 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 +266,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]