Skip to content

Commit 6916263

Browse files
committed
feat: Add --path-style=all option to managed command
1 parent 0837305 commit 6916263

File tree

9 files changed

+117
-20
lines changed

9 files changed

+117
-20
lines changed

assets/chezmoi.io/docs/reference/commands/managed.md

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ the destination directory in alphabetical order.
1010

1111
--8<-- "common-flags/exclude.md"
1212

13+
### `-f`, `--format` `json`|`yaml`
14+
15+
--8<-- "common-flags/format.md"
16+
1317
### `-i`, `--include` *types*
1418

1519
--8<-- "common-flags/include.md"

assets/chezmoi.io/snippets/common-flags/path-style.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ Print paths in the given style. The default is `relative`.
99
--8<-- [end:no-source-tree]
1010
| `source-absolute` | Absolute paths in the source tree directory |
1111
| `source-relative` | Relative paths to the source tree directory |
12+
| `all` | All path styles, indexed by relative |
1213
--8<-- [end:all]

internal/chezmoi/relpath.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ func (p RelPath) Less(other RelPath) bool {
8989
return p.relPath < other.relPath
9090
}
9191

92-
// MarshalJSON implements encoding.TextMarshaler.MarshalJSON.
93-
func (p RelPath) MarshalJSON() ([]byte, error) {
94-
return FormatJSON.Marshal(p.relPath)
92+
// MarshalText implements encoding.TextMarshaler.MarshalText.
93+
func (p RelPath) MarshalText() ([]byte, error) {
94+
return []byte(p.relPath), nil
9595
}
9696

9797
// Slice returns a part of p.

internal/chezmoi/sourcerelpath.go

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ func (p SourceRelPath) Less(other SourceRelPath) bool {
6161
return p.relPath.Less(other.relPath)
6262
}
6363

64+
// MarshalText implements encoding.TextMarshaler.MarshalText.
65+
func (p SourceRelPath) MarshalText() ([]byte, error) {
66+
return []byte(p.relPath.String()), nil
67+
}
68+
6469
// RelPath returns p as a relative path.
6570
func (p SourceRelPath) RelPath() RelPath {
6671
return p.relPath

internal/cmd/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ func newConfig(options ...configOption) (*Config, error) {
381381
},
382382
managed: managedCmdConfig{
383383
filter: chezmoi.NewEntryTypeFilter(chezmoi.EntryTypesAll, chezmoi.EntryTypesNone),
384+
format: newChoiceFlag(formatJSON, writeDataFormatValues),
384385
pathStyle: newChoiceFlag(pathStyleRelative, sourceOrTargetPathStyleValues),
385386
},
386387
mergeAll: mergeAllCmdConfig{

internal/cmd/managedcmd.go

+43-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"cmp"
45
"fmt"
56

67
"github.com/spf13/cobra"
@@ -10,6 +11,7 @@ import (
1011

1112
type managedCmdConfig struct {
1213
filter *chezmoi.EntryTypeFilter
14+
format *choiceFlag
1315
pathStyle *choiceFlag
1416
tree bool
1517
}
@@ -29,6 +31,7 @@ func (c *Config) newManagedCmd() *cobra.Command {
2931
}
3032

3133
managedCmd.Flags().VarP(c.managed.filter.Exclude, "exclude", "x", "Exclude entry types")
34+
managedCmd.Flags().VarP(c.managed.format, "format", "f", "Format")
3235
managedCmd.Flags().VarP(c.managed.filter.Include, "include", "i", "Include entry types")
3336
managedCmd.Flags().VarP(c.managed.pathStyle, "path-style", "p", "Path style")
3437
must(managedCmd.RegisterFlagCompletionFunc("path-style", c.managed.pathStyle.FlagCompletionFunc()))
@@ -51,7 +54,13 @@ func (c *Config) runManagedCmd(cmd *cobra.Command, args []string, sourceState *c
5154
}
5255
}
5356

54-
var paths []fmt.Stringer
57+
type entryPaths struct {
58+
targetRelPath chezmoi.RelPath
59+
Absolute chezmoi.AbsPath `json:"absolute" yaml:"absolute"`
60+
SourceAbsolute chezmoi.AbsPath `json:"sourceAbsolute" yaml:"sourceAbsolute"`
61+
SourceRelative chezmoi.SourceRelPath `json:"sourceRelative" yaml:"sourceRelative"`
62+
}
63+
var allEntryPaths []*entryPaths
5564
_ = sourceState.ForEach(
5665
func(targetRelPath chezmoi.RelPath, sourceStateEntry chezmoi.SourceStateEntry) error {
5766
if !c.managed.filter.IncludeSourceStateEntry(sourceStateEntry) {
@@ -80,25 +89,42 @@ func (c *Config) runManagedCmd(cmd *cobra.Command, args []string, sourceState *c
8089
}
8190
}
8291

83-
var path fmt.Stringer
84-
switch pathStyle := c.managed.pathStyle.String(); pathStyle {
85-
case pathStyleAbsolute:
86-
path = c.DestDirAbsPath.Join(targetRelPath)
87-
case pathStyleRelative:
88-
path = targetRelPath
89-
case pathStyleSourceAbsolute:
90-
path = c.SourceDirAbsPath.Join(sourceStateEntry.SourceRelPath().RelPath())
91-
case pathStyleSourceRelative:
92-
path = sourceStateEntry.SourceRelPath().RelPath()
93-
default:
94-
return fmt.Errorf("%s: invalid path style", pathStyle)
92+
entryPaths := &entryPaths{
93+
targetRelPath: targetRelPath,
94+
Absolute: c.DestDirAbsPath.Join(targetRelPath),
95+
SourceAbsolute: c.SourceDirAbsPath.Join(sourceStateEntry.SourceRelPath().RelPath()),
96+
SourceRelative: sourceStateEntry.SourceRelPath(),
9597
}
96-
paths = append(paths, path)
98+
allEntryPaths = append(allEntryPaths, entryPaths)
9799
return nil
98100
},
99101
)
100102

101-
return c.writePaths(stringersToStrings(paths), writePathsOptions{
102-
tree: c.managed.tree,
103-
})
103+
switch pathStyle := c.managed.pathStyle.String(); pathStyle {
104+
case pathStyleAbsolute, pathStyleRelative, pathStyleSourceAbsolute, pathStyleSourceRelative:
105+
paths := make([]string, len(allEntryPaths))
106+
for i, structuredPath := range allEntryPaths {
107+
switch c.managed.pathStyle.String() {
108+
case pathStyleAbsolute:
109+
paths[i] = structuredPath.Absolute.String()
110+
case pathStyleRelative:
111+
paths[i] = structuredPath.targetRelPath.String()
112+
case pathStyleSourceAbsolute:
113+
paths[i] = structuredPath.SourceAbsolute.String()
114+
case pathStyleSourceRelative:
115+
paths[i] = structuredPath.SourceRelative.String()
116+
}
117+
}
118+
return c.writePaths(paths, writePathsOptions{
119+
tree: c.managed.tree,
120+
})
121+
case pathStyleAll:
122+
allEntryPathsMap := make(map[string]*entryPaths, len(allEntryPaths))
123+
for _, entryPaths := range allEntryPaths {
124+
allEntryPathsMap[entryPaths.targetRelPath.String()] = entryPaths
125+
}
126+
return c.marshal(cmp.Or(c.managed.format.String(), c.Format.String()), allEntryPathsMap)
127+
default:
128+
return fmt.Errorf("%s: invalid path style", pathStyle)
129+
}
104130
}

internal/cmd/pathstyle.go

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const (
55
pathStyleRelative = "relative"
66
pathStyleSourceAbsolute = "source-absolute"
77
pathStyleSourceRelative = "source-relative"
8+
pathStyleAll = "all"
89
)
910

1011
var (
@@ -13,6 +14,7 @@ var (
1314
pathStyleRelative,
1415
pathStyleSourceAbsolute,
1516
pathStyleSourceRelative,
17+
pathStyleAll,
1618
}
1719
targetPathStyleValues = []string{
1820
pathStyleAbsolute,

internal/cmd/testdata/scripts/completion.txtar

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ relative
140140
:4
141141
-- golden/path-style-with-source --
142142
absolute
143+
all
143144
relative
144145
source-absolute
145146
source-relative

internal/cmd/testdata/scripts/managed.txtar

+57
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ chhome home2/user
7878
exec chezmoi managed --include=all
7979
cmp stdout golden/managed2
8080

81+
# test chezmoi managed --path-style=all
82+
[!windows] exec chezmoi managed --path-style=all
83+
[!windows] cmpenv stdout golden/managed-all.json
84+
85+
# test chezmoi managed --path-style=all --format=yaml
86+
[!windows] exec chezmoi managed --path-style=all --format=yaml
87+
[!windows] cmpenv stdout golden/managed-all.yaml
88+
8189
-- golden/managed --
8290
.create
8391
.dir
@@ -108,6 +116,55 @@ $WORK/home/user/.readonly
108116
$WORK/home/user/.remove
109117
$WORK/home/user/.symlink
110118
$WORK/home/user/.template
119+
-- golden/managed-all.json --
120+
{
121+
".create": {
122+
"absolute": "$WORK/home2/user/.create",
123+
"sourceAbsolute": "$WORK/home2/user/.local/share/chezmoi/create_dot_create.tmpl",
124+
"sourceRelative": "create_dot_create.tmpl"
125+
},
126+
".file": {
127+
"absolute": "$WORK/home2/user/.file",
128+
"sourceAbsolute": "$WORK/home2/user/.local/share/chezmoi/modify_dot_file.tmpl",
129+
"sourceRelative": "modify_dot_file.tmpl"
130+
},
131+
".symlink": {
132+
"absolute": "$WORK/home2/user/.symlink",
133+
"sourceAbsolute": "$WORK/home2/user/.local/share/chezmoi/symlink_dot_symlink.tmpl",
134+
"sourceRelative": "symlink_dot_symlink.tmpl"
135+
},
136+
".template": {
137+
"absolute": "$WORK/home2/user/.template",
138+
"sourceAbsolute": "$WORK/home2/user/.local/share/chezmoi/dot_template.tmpl",
139+
"sourceRelative": "dot_template.tmpl"
140+
},
141+
"script": {
142+
"absolute": "$WORK/home2/user/script",
143+
"sourceAbsolute": "$WORK/home2/user/.local/share/chezmoi/run_script.tmpl",
144+
"sourceRelative": "run_script.tmpl"
145+
}
146+
}
147+
-- golden/managed-all.yaml --
148+
.create:
149+
absolute: $WORK/home2/user/.create
150+
sourceAbsolute: $WORK/home2/user/.local/share/chezmoi/create_dot_create.tmpl
151+
sourceRelative: create_dot_create.tmpl
152+
.file:
153+
absolute: $WORK/home2/user/.file
154+
sourceAbsolute: $WORK/home2/user/.local/share/chezmoi/modify_dot_file.tmpl
155+
sourceRelative: modify_dot_file.tmpl
156+
.symlink:
157+
absolute: $WORK/home2/user/.symlink
158+
sourceAbsolute: $WORK/home2/user/.local/share/chezmoi/symlink_dot_symlink.tmpl
159+
sourceRelative: symlink_dot_symlink.tmpl
160+
.template:
161+
absolute: $WORK/home2/user/.template
162+
sourceAbsolute: $WORK/home2/user/.local/share/chezmoi/dot_template.tmpl
163+
sourceRelative: dot_template.tmpl
164+
script:
165+
absolute: $WORK/home2/user/script
166+
sourceAbsolute: $WORK/home2/user/.local/share/chezmoi/run_script.tmpl
167+
sourceRelative: run_script.tmpl
111168
-- golden/managed-exclude-encrypted --
112169
.create
113170
.dir

0 commit comments

Comments
 (0)