Skip to content

Commit 989e69d

Browse files
Merge pull request #1929 from giuseppe/compose-fs-add-missing-dir-parents
composefs: add parent directory if missing
2 parents c42fcc5 + 6b1c044 commit 989e69d

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

pkg/chunked/dump/dump.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,23 @@ func sanitizeName(name string) string {
104104
return path
105105
}
106106

107-
func dumpNode(out io.Writer, links map[string]int, verityDigests map[string]string, entry *internal.FileMetadata) error {
107+
func dumpNode(out io.Writer, added map[string]struct{}, links map[string]int, verityDigests map[string]string, entry *internal.FileMetadata) error {
108108
path := sanitizeName(entry.Name)
109109

110+
parent := filepath.Dir(path)
111+
if _, found := added[parent]; !found && entry.Name != "/" {
112+
parentEntry := &internal.FileMetadata{
113+
Name: parent,
114+
Type: internal.TypeDir,
115+
Mode: 0o755,
116+
}
117+
if err := dumpNode(out, added, links, verityDigests, parentEntry); err != nil {
118+
return err
119+
}
120+
121+
}
122+
added[path] = struct{}{}
123+
110124
if _, err := fmt.Fprint(out, escaped(path, ESCAPE_STANDARD)); err != nil {
111125
return err
112126
}
@@ -201,6 +215,7 @@ func GenerateDump(tocI interface{}, verityDigests map[string]string) (io.Reader,
201215
}()
202216

203217
links := make(map[string]int)
218+
added := make(map[string]struct{})
204219
for _, e := range toc.Entries {
205220
if e.Linkname == "" {
206221
continue
@@ -211,14 +226,14 @@ func GenerateDump(tocI interface{}, verityDigests map[string]string) (io.Reader,
211226
links[e.Linkname] = links[e.Linkname] + 1
212227
}
213228

214-
if len(toc.Entries) == 0 || (sanitizeName(toc.Entries[0].Name) != "/") {
229+
if len(toc.Entries) == 0 {
215230
root := &internal.FileMetadata{
216231
Name: "/",
217232
Type: internal.TypeDir,
218233
Mode: 0o755,
219234
}
220235

221-
if err := dumpNode(w, links, verityDigests, root); err != nil {
236+
if err := dumpNode(w, added, links, verityDigests, root); err != nil {
222237
pipeW.CloseWithError(err)
223238
closed = true
224239
return
@@ -229,7 +244,7 @@ func GenerateDump(tocI interface{}, verityDigests map[string]string) (io.Reader,
229244
if e.Type == internal.TypeChunk {
230245
continue
231246
}
232-
if err := dumpNode(w, links, verityDigests, &e); err != nil {
247+
if err := dumpNode(w, added, links, verityDigests, &e); err != nil {
233248
pipeW.CloseWithError(err)
234249
closed = true
235250
return

pkg/chunked/dump/dump_test.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,37 +87,52 @@ func TestDumpNode(t *testing.T) {
8787
Linkname: "existingfile",
8888
}
8989

90-
var bufRegularFile, bufDirectory, bufSymlink, bufHardlink bytes.Buffer
90+
missingParentEntry := &internal.FileMetadata{
91+
Name: "foo/bar/baz/entry",
92+
Type: internal.TypeReg,
93+
ModTime: &modTime,
94+
}
95+
96+
var bufRegularFile, bufDirectory, bufSymlink, bufHardlink, bufMissingParent bytes.Buffer
9197

92-
err := dumpNode(&bufRegularFile, map[string]int{}, map[string]string{}, regularFileEntry)
98+
added := map[string]struct{}{"/": {}}
99+
100+
err := dumpNode(&bufRegularFile, added, map[string]int{}, map[string]string{}, regularFileEntry)
93101
if err != nil {
94102
t.Errorf("unexpected error for regular file: %v", err)
95103
}
96104

97-
err = dumpNode(&bufDirectory, map[string]int{}, map[string]string{}, directoryEntry)
105+
err = dumpNode(&bufDirectory, added, map[string]int{}, map[string]string{}, directoryEntry)
98106
if err != nil {
99107
t.Errorf("unexpected error for directory: %v", err)
100108
}
101109

102-
err = dumpNode(&bufSymlink, map[string]int{}, map[string]string{}, symlinkEntry)
110+
err = dumpNode(&bufSymlink, added, map[string]int{}, map[string]string{}, symlinkEntry)
103111
if err != nil {
104112
t.Errorf("unexpected error for symlink: %v", err)
105113
}
106114

107-
err = dumpNode(&bufHardlink, map[string]int{}, map[string]string{}, hardlinkEntry)
115+
err = dumpNode(&bufHardlink, added, map[string]int{}, map[string]string{}, hardlinkEntry)
108116
if err != nil {
109117
t.Errorf("unexpected error for hardlink: %v", err)
110118
}
111119

120+
err = dumpNode(&bufMissingParent, added, map[string]int{}, map[string]string{}, missingParentEntry)
121+
if err != nil {
122+
t.Errorf("unexpected error: %v", err)
123+
}
124+
112125
expectedRegularFile := "/example.txt 100 100000 1 1000 1000 0 1672531200.0 ab/cdef1234567890 - - user.key1=value1\n"
113126
expectedDirectory := "/mydir 0 40000 1 1000 1000 0 1672531200.0 - - - user.key2=value2\n"
114127
expectedSymlink := "/mysymlink 0 120000 1 0 0 0 1672531200.0 targetfile - -\n"
115128
expectedHardlink := "/myhardlink 0 @100000 1 0 0 0 1672531200.0 /existingfile - -\n"
129+
expectedActualMissingParent := "/foo 0 40755 1 0 0 0 0.0 - - -\n/foo/bar 0 40755 1 0 0 0 0.0 - - -\n/foo/bar/baz 0 40755 1 0 0 0 0.0 - - -\n/foo/bar/baz/entry 0 100000 1 0 0 0 1672531200.0 - - -\n"
116130

117131
actualRegularFile := bufRegularFile.String()
118132
actualDirectory := bufDirectory.String()
119133
actualSymlink := bufSymlink.String()
120134
actualHardlink := bufHardlink.String()
135+
actualMissingParent := bufMissingParent.String()
121136

122137
if actualRegularFile != expectedRegularFile {
123138
t.Errorf("for regular file, got %q, want %q", actualRegularFile, expectedRegularFile)
@@ -134,4 +149,7 @@ func TestDumpNode(t *testing.T) {
134149
if actualHardlink != expectedHardlink {
135150
t.Errorf("for hardlink, got %q, want %q", actualHardlink, expectedHardlink)
136151
}
152+
if actualMissingParent != expectedActualMissingParent {
153+
t.Errorf("for missing parent, got %q, want %q", actualMissingParent, expectedActualMissingParent)
154+
}
137155
}

0 commit comments

Comments
 (0)