... | ... |
@@ -110,12 +110,44 @@ func (graph *Graph) Garbage() (*Graph, error) { |
110 | 110 |
return NewGraph(path.Join(graph.Root, ":garbage:")) |
111 | 111 |
} |
112 | 112 |
|
113 |
+// Check if given error is "not empty" |
|
114 |
+// Note: this is the way golang do it internally with os.IsNotExists |
|
115 |
+func isNotEmpty(err error) bool { |
|
116 |
+ switch pe := err.(type) { |
|
117 |
+ case nil: |
|
118 |
+ return false |
|
119 |
+ case *os.PathError: |
|
120 |
+ err = pe.Err |
|
121 |
+ case *os.LinkError: |
|
122 |
+ err = pe.Err |
|
123 |
+ } |
|
124 |
+ return strings.Contains(err.Error(), " not empty") |
|
125 |
+} |
|
126 |
+ |
|
113 | 127 |
func (graph *Graph) Delete(id string) error { |
114 | 128 |
garbage, err := graph.Garbage() |
115 | 129 |
if err != nil { |
116 | 130 |
return err |
117 | 131 |
} |
118 |
- return os.Rename(graph.imageRoot(id), garbage.imageRoot(id)) |
|
132 |
+ err = os.Rename(graph.imageRoot(id), garbage.imageRoot(id)) |
|
133 |
+ if err != nil { |
|
134 |
+ if isNotEmpty(err) { |
|
135 |
+ Debugf("The image %s is already present in garbage. Removing it.", id) |
|
136 |
+ if err = os.RemoveAll(garbage.imageRoot(id)); err != nil { |
|
137 |
+ Debugf("Error while removing the image %s from garbage: %s\n", id, err) |
|
138 |
+ return err |
|
139 |
+ } |
|
140 |
+ Debugf("Image %s removed from garbage", id) |
|
141 |
+ if err = os.Rename(graph.imageRoot(id), garbage.imageRoot(id)); err != nil { |
|
142 |
+ return err |
|
143 |
+ } |
|
144 |
+ Debugf("Image %s put in the garbage", id) |
|
145 |
+ } else { |
|
146 |
+ Debugf("Error putting the image %s to garbage: %s\n", id, err) |
|
147 |
+ } |
|
148 |
+ return err |
|
149 |
+ } |
|
150 |
+ return nil |
|
119 | 151 |
} |
120 | 152 |
|
121 | 153 |
func (graph *Graph) Undelete(id string) error { |
... | ... |
@@ -158,6 +158,14 @@ func TestDelete(t *testing.T) { |
158 | 158 |
} |
159 | 159 |
assertNImages(graph, t, 1) |
160 | 160 |
|
161 |
+ // Test delete twice (pull -> rm -> pull -> rm) |
|
162 |
+ if err := graph.Register(archive, img1); err != nil { |
|
163 |
+ t.Fatal(err) |
|
164 |
+ } |
|
165 |
+ if err := graph.Delete(img1.Id); err != nil { |
|
166 |
+ t.Fatal(err) |
|
167 |
+ } |
|
168 |
+ assertNImages(graph, t, 1) |
|
161 | 169 |
} |
162 | 170 |
|
163 | 171 |
func assertNImages(graph *Graph, t *testing.T, n int) { |