X-Git-Url: https://ruderich.org/simon/gitweb/?p=safcm%2Fsafcm.git;a=blobdiff_plain;f=frontend%2Fchanges.go;fp=cmd%2Fsafcm%2Fsync_changes.go;h=351cdfac181a7a054350584453d5133e3606b371;hp=2650bb46062b33ab0f86e75d9b0f0cb1643bf556;hb=ecbcb0132728cc18016819a214378b642d92278e;hpb=b0f49e5d47786984e24731b200d3d3d7d6add263 diff --git a/cmd/safcm/sync_changes.go b/frontend/changes.go similarity index 76% rename from cmd/safcm/sync_changes.go rename to frontend/changes.go index 2650bb4..351cdfa 100644 --- a/cmd/safcm/sync_changes.go +++ b/frontend/changes.go @@ -1,4 +1,4 @@ -// "sync" sub-command: format changes +// Frontend: Format changes // Copyright (C) 2021 Simon Ruderich // @@ -15,7 +15,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -package main +package frontend import ( "fmt" @@ -30,23 +30,29 @@ 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 { +type Changes struct { + DryRun bool + Quiet bool + IsTTY bool +} + +func (c *Changes) FormatChanges(resp safcm.MsgSyncResp) string { var changes []string if len(resp.FileChanges) > 0 { changes = append(changes, - s.formatFileChanges(resp.FileChanges)) + c.FormatFileChanges(resp.FileChanges)) } if len(resp.PackageChanges) > 0 { changes = append(changes, - s.formatPackageChanges(resp.PackageChanges)) + c.FormatPackageChanges(resp.PackageChanges)) } if len(resp.ServiceChanges) > 0 { changes = append(changes, - s.formatServiceChanges(resp.ServiceChanges)) + c.FormatServiceChanges(resp.ServiceChanges)) } if len(resp.CommandChanges) > 0 { changes = append(changes, - s.formatCommandChanges(resp.CommandChanges)) + c.FormatCommandChanges(resp.CommandChanges)) } if len(changes) == 0 { // Notify user that the host was synced successfully @@ -64,30 +70,30 @@ func (s *Sync) formatChanges(resp safcm.MsgSyncResp) string { return "\n" + x } -func (s *Sync) formatFileChanges(changes []safcm.FileChange) string { +func (c *Changes) FormatFileChanges(changes []safcm.FileChange) string { var buf strings.Builder - if s.config.DryRun { + if c.DryRun { fmt.Fprintf(&buf, "will change %d file(s): (dry-run)\n", len(changes)) } else { fmt.Fprintf(&buf, "changed %d file(s):\n", len(changes)) } for _, x := range changes { - fmt.Fprintf(&buf, "%s:", s.formatTarget(x.Path)) + fmt.Fprintf(&buf, "%s:", c.FormatTarget(x.Path)) var info []string if x.Created { info = append(info, - ColorString(s.isTTY, ColorGreen, "created"), - formatFileType(x.New), - formatFileUserGroup(x.New), - formatFilePerm(x.New), + ColorString(c.IsTTY, ColorGreen, "created"), + FormatFileType(x.New), + FormatFileUserGroup(x.New), + FormatFilePerm(x.New), ) } else { if x.Old.Mode.Type() != x.New.Mode.Type() { info = append(info, fmt.Sprintf("%s -> %s", - formatFileType(x.Old), - formatFileType(x.New), + FormatFileType(x.Old), + FormatFileType(x.New), )) } if x.Old.User != x.New.User || @@ -95,15 +101,15 @@ func (s *Sync) formatFileChanges(changes []safcm.FileChange) string { x.Old.Group != x.New.Group || x.Old.Gid != x.New.Gid { info = append(info, fmt.Sprintf("%s -> %s", - formatFileUserGroup(x.Old), - formatFileUserGroup(x.New), + FormatFileUserGroup(x.Old), + FormatFileUserGroup(x.New), )) } if config.FileModeToFullPerm(x.Old.Mode) != config.FileModeToFullPerm(x.New.Mode) { info = append(info, fmt.Sprintf("%s -> %s", - formatFilePerm(x.Old), - formatFilePerm(x.New), + FormatFilePerm(x.Old), + FormatFilePerm(x.New), )) } } @@ -113,13 +119,14 @@ func (s *Sync) formatFileChanges(changes []safcm.FileChange) string { } if x.DataDiff != "" { - fmt.Fprintf(&buf, "\n%s", s.formatDiff(x.DataDiff)) + fmt.Fprintf(&buf, "\n%s", c.FormatDiff(x.DataDiff)) } fmt.Fprintf(&buf, "\n") } return buf.String() } -func formatFileType(info safcm.FileChangeInfo) string { + +func FormatFileType(info safcm.FileChangeInfo) string { switch info.Mode.Type() { case 0: // regular file return "file" @@ -131,18 +138,18 @@ func formatFileType(info safcm.FileChangeInfo) string { return fmt.Sprintf("invalid type %v", info.Mode.Type()) } } -func formatFileUserGroup(info safcm.FileChangeInfo) string { +func FormatFileUserGroup(info safcm.FileChangeInfo) string { return fmt.Sprintf("%s(%d) %s(%d)", EscapeControlCharacters(false, info.User), info.Uid, EscapeControlCharacters(false, info.Group), info.Gid) } -func formatFilePerm(info safcm.FileChangeInfo) string { +func FormatFilePerm(info safcm.FileChangeInfo) string { return fmt.Sprintf("%#o", config.FileModeToFullPerm(info.Mode)) } -func (s *Sync) formatPackageChanges(changes []safcm.PackageChange) string { +func (c *Changes) FormatPackageChanges(changes []safcm.PackageChange) string { var buf strings.Builder - if s.config.DryRun { + if c.DryRun { fmt.Fprintf(&buf, "will install %d package(s): (dry-run)\n", len(changes)) } else { @@ -150,14 +157,14 @@ func (s *Sync) formatPackageChanges(changes []safcm.PackageChange) string { } for _, x := range changes { // TODO: indicate if installation failed - fmt.Fprintf(&buf, "%s\n", s.formatTarget(x.Name)) + fmt.Fprintf(&buf, "%s\n", c.FormatTarget(x.Name)) } return buf.String() } -func (s *Sync) formatServiceChanges(changes []safcm.ServiceChange) string { +func (c *Changes) FormatServiceChanges(changes []safcm.ServiceChange) string { var buf strings.Builder - if s.config.DryRun { + if c.DryRun { fmt.Fprintf(&buf, "will modify %d service(s): (dry-run)\n", len(changes)) } else { @@ -172,13 +179,13 @@ func (s *Sync) formatServiceChanges(changes []safcm.ServiceChange) string { info = append(info, "enabled") } fmt.Fprintf(&buf, "%s: %s\n", - s.formatTarget(x.Name), + c.FormatTarget(x.Name), strings.Join(info, ", ")) } return buf.String() } -func (s *Sync) formatCommandChanges(changes []safcm.CommandChange) string { +func (c *Changes) FormatCommandChanges(changes []safcm.CommandChange) string { const indent = " > " // Quiet hides all successful, non-trigger commands which produce no @@ -188,7 +195,7 @@ func (s *Sync) formatCommandChanges(changes []safcm.CommandChange) string { // 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 { + if c.Quiet { for _, x := range changes { if x.Trigger == "" && x.Error == "" && @@ -199,18 +206,18 @@ func (s *Sync) formatCommandChanges(changes []safcm.CommandChange) string { } var buf strings.Builder - if s.config.DryRun { + if c.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 { + if noOutput > 0 && !c.DryRun { fmt.Fprintf(&buf, ", %d with no output (hidden)", noOutput) } if noOutput != len(changes) { fmt.Fprintf(&buf, ":") } - if s.config.DryRun { + if c.DryRun { fmt.Fprintf(&buf, " (dry-run)") } fmt.Fprintf(&buf, "\n") @@ -220,7 +227,7 @@ func (s *Sync) formatCommandChanges(changes []safcm.CommandChange) string { continue } - fmt.Fprintf(&buf, "%s", s.formatTarget(x.Command)) + fmt.Fprintf(&buf, "%s", c.FormatTarget(x.Command)) if x.Trigger != "" { fmt.Fprintf(&buf, ", trigger for %q", x.Trigger) } @@ -231,34 +238,34 @@ func (s *Sync) formatCommandChanges(changes []safcm.CommandChange) string { // TODO: truncate very large outputs? x := indentBlock(x.Output, indent) fmt.Fprintf(&buf, ":\n%s", - EscapeControlCharacters(s.isTTY, x)) + EscapeControlCharacters(c.IsTTY, x)) } fmt.Fprintf(&buf, "\n") } return buf.String() } -func (s *Sync) formatTarget(x string) string { +func (c *Changes) FormatTarget(x string) string { x = fmt.Sprintf("%q", x) // escape! - return ColorString(s.isTTY, ColorCyan, x) + return ColorString(c.IsTTY, ColorCyan, x) } -func (s *Sync) formatDiff(diff string) string { +func (c *Changes) FormatDiff(diff string) string { const indent = " " diff = indentBlock(diff, indent) // Never color diff content as we want to color the whole diff diff = EscapeControlCharacters(false, diff) - if !s.isTTY { + if !c.IsTTY { return diff } var res []string for _, x := range strings.Split(diff, "\n") { if strings.HasPrefix(x, indent+"+") { - x = ColorString(s.isTTY, ColorGreen, x) + x = ColorString(c.IsTTY, ColorGreen, x) } else if strings.HasPrefix(x, indent+"-") { - x = ColorString(s.isTTY, ColorRed, x) + x = ColorString(c.IsTTY, ColorRed, x) } res = append(res, x) }