| ... | ... |
@@ -705,26 +705,22 @@ func (srv *Server) ContainerDestroy(name string, removeVolume bool) error {
|
| 705 | 705 |
return nil |
| 706 | 706 |
} |
| 707 | 707 |
|
| 708 |
-func (srv *Server) pruneImage(img *Image, repo, tag string) error {
|
|
| 709 |
- return nil |
|
| 710 |
-} |
|
| 711 |
- |
|
| 712 | 708 |
var ErrImageReferenced = errors.New("Image referenced by a repository")
|
| 713 | 709 |
|
| 714 |
-func (srv *Server) deleteImageChildren(id string, byId map[string][]string, byParents map[string][]*Image) error {
|
|
| 710 |
+func (srv *Server) deleteImageAndChildren(id string) error {
|
|
| 715 | 711 |
// If the image is referenced by a repo, do not delete |
| 716 |
- if len(byId[id]) != 0 {
|
|
| 712 |
+ if len(srv.runtime.repositories.ById()[id]) != 0 {
|
|
| 717 | 713 |
return ErrImageReferenced |
| 718 | 714 |
} |
| 719 |
- // If the image is not referenced and has no children, remove it |
|
| 720 |
- if len(byParents[id]) == 0 {
|
|
| 721 |
- return srv.runtime.graph.Delete(id) |
|
| 722 |
- } |
|
| 723 | 715 |
|
| 724 | 716 |
// If the image is not referenced but has children, go recursive |
| 725 | 717 |
referenced := false |
| 718 |
+ byParents, err := srv.runtime.graph.ByParent() |
|
| 719 |
+ if err != nil {
|
|
| 720 |
+ return err |
|
| 721 |
+ } |
|
| 726 | 722 |
for _, img := range byParents[id] {
|
| 727 |
- if err := srv.deleteImageChildren(img.Id, byId, byParents); err != nil {
|
|
| 723 |
+ if err := srv.deleteImageAndChildren(img.Id); err != nil {
|
|
| 728 | 724 |
if err != ErrImageReferenced {
|
| 729 | 725 |
return err |
| 730 | 726 |
} else {
|
| ... | ... |
@@ -735,56 +731,61 @@ func (srv *Server) deleteImageChildren(id string, byId map[string][]string, byPa |
| 735 | 735 |
if referenced {
|
| 736 | 736 |
return ErrImageReferenced |
| 737 | 737 |
} |
| 738 |
+ |
|
| 739 |
+ // If the image is not referenced and has no children, remove it |
|
| 740 |
+ byParents, err = srv.runtime.graph.ByParent() |
|
| 741 |
+ if err != nil {
|
|
| 742 |
+ return err |
|
| 743 |
+ } |
|
| 744 |
+ if len(byParents[id]) == 0 {
|
|
| 745 |
+ if err := srv.runtime.repositories.DeleteAll(id); err != nil {
|
|
| 746 |
+ return err |
|
| 747 |
+ } |
|
| 748 |
+ return srv.runtime.graph.Delete(id) |
|
| 749 |
+ } |
|
| 738 | 750 |
return nil |
| 739 | 751 |
} |
| 740 | 752 |
|
| 741 |
-func (srv *Server) deleteImageParents(img *Image, byId map[string][]string, byParents map[string][]*Image) error {
|
|
| 753 |
+func (srv *Server) deleteImageParents(img *Image) error {
|
|
| 742 | 754 |
if img.Parent != "" {
|
| 743 | 755 |
parent, err := srv.runtime.graph.Get(img.Parent) |
| 744 | 756 |
if err != nil {
|
| 745 | 757 |
return err |
| 746 | 758 |
} |
| 747 | 759 |
// Remove all children images |
| 748 |
- if err := srv.deleteImageChildren(img.Id, byId, byParents); err != nil {
|
|
| 760 |
+ if err := srv.deleteImageAndChildren(img.Parent); err != nil {
|
|
| 749 | 761 |
return err |
| 750 | 762 |
} |
| 751 |
- // If no error (no referenced children), then remove the parent |
|
| 752 |
- if err := srv.runtime.graph.Delete(img.Parent); err != nil {
|
|
| 753 |
- return err |
|
| 754 |
- } |
|
| 755 |
- return srv.deleteImageParents(parent, byId, byParents) |
|
| 763 |
+ return srv.deleteImageParents(parent) |
|
| 756 | 764 |
} |
| 757 | 765 |
return nil |
| 758 | 766 |
} |
| 759 | 767 |
|
| 760 |
-func (srv *Server) deleteImage(repoName, tag string) error {
|
|
| 761 |
- img, err := srv.runtime.repositories.LookupImage(repoName + ":" + tag) |
|
| 762 |
- if err != nil {
|
|
| 763 |
- return fmt.Errorf("No such image: %s:%s", repoName, tag)
|
|
| 764 |
- } |
|
| 765 |
- utils.Debugf("Image %s referenced %d times", img.Id, len(srv.runtime.repositories.ById()[img.Id]))
|
|
| 766 |
- if err := srv.runtime.repositories.Delete(repoName, tag, img.Id); err != nil {
|
|
| 768 |
+func (srv *Server) deleteImage(img *Image, repoName, tag string) error {
|
|
| 769 |
+ //Untag the current image |
|
| 770 |
+ if err := srv.runtime.repositories.Delete(repoName, tag); err != nil {
|
|
| 767 | 771 |
return err |
| 768 | 772 |
} |
| 769 |
- byId := srv.runtime.repositories.ById() |
|
| 770 |
- if len(byId[img.Id]) == 0 {
|
|
| 771 |
- byParents, err := srv.runtime.graph.ByParent() |
|
| 772 |
- if err != nil {
|
|
| 773 |
- return err |
|
| 774 |
- } |
|
| 775 |
- if err := srv.deleteImageChildren(img.Id, byId, byParents); err != nil {
|
|
| 773 |
+ if len(srv.runtime.repositories.ById()[img.Id]) == 0 {
|
|
| 774 |
+ if err := srv.deleteImageAndChildren(img.Id); err != nil {
|
|
| 775 |
+ if err != ErrImageReferenced {
|
|
| 776 |
+ return err |
|
| 777 |
+ } |
|
| 778 |
+ } else if err := srv.deleteImageParents(img); err != nil {
|
|
| 776 | 779 |
if err != ErrImageReferenced {
|
| 777 | 780 |
return err |
| 778 | 781 |
} |
| 779 |
- } else {
|
|
| 780 |
- srv.deleteImageParents(img) |
|
| 781 | 782 |
} |
| 782 |
- |
|
| 783 | 783 |
} |
| 784 | 784 |
return nil |
| 785 | 785 |
} |
| 786 | 786 |
|
| 787 | 787 |
func (srv *Server) ImageDelete(name string) error {
|
| 788 |
+ img, err := srv.runtime.repositories.LookupImage(name) |
|
| 789 |
+ if err != nil {
|
|
| 790 |
+ return fmt.Errorf("No such image: %s", name)
|
|
| 791 |
+ } |
|
| 792 |
+ |
|
| 788 | 793 |
var tag string |
| 789 | 794 |
if strings.Contains(name, ":") {
|
| 790 | 795 |
nameParts := strings.Split(name, ":") |
| ... | ... |
@@ -792,40 +793,7 @@ func (srv *Server) ImageDelete(name string) error {
|
| 792 | 792 |
tag = nameParts[1] |
| 793 | 793 |
} |
| 794 | 794 |
|
| 795 |
- srv.deleteImage(name, tag) |
|
| 796 |
- |
|
| 797 |
- // if the images is referenced several times |
|
| 798 |
- |
|
| 799 |
- // check is the image to delete isn't parent of another image |
|
| 800 |
- byParent, _ := srv.runtime.graph.ByParent() |
|
| 801 |
- if childs, exists := byParent[img.Id]; exists {
|
|
| 802 |
- if strings.Contains(img.Id, name) {
|
|
| 803 |
- return fmt.Errorf("Conflict with %s, %s was not removed", childs[0].ShortId(), name)
|
|
| 804 |
- } |
|
| 805 |
- if err := srv.runtime.repositories.Delete(name, tag, img.Id); err != nil {
|
|
| 806 |
- return err |
|
| 807 |
- } |
|
| 808 |
- return nil |
|
| 809 |
- } |
|
| 810 |
- parents, _ := img.History() |
|
| 811 |
- for _, parent := range parents {
|
|
| 812 |
- byParent, _ = srv.runtime.graph.ByParent() |
|
| 813 |
- //stop if image has children |
|
| 814 |
- if _, exists := byParent[parent.Id]; exists {
|
|
| 815 |
- break |
|
| 816 |
- } |
|
| 817 |
- //stop if image is tagged and it is not the first image we delete |
|
| 818 |
- if _, hasTags := srv.runtime.repositories.ById()[parent.Id]; hasTags && img.Id != parent.Id {
|
|
| 819 |
- break |
|
| 820 |
- } |
|
| 821 |
- if err := srv.runtime.graph.Delete(parent.Id); err != nil {
|
|
| 822 |
- return fmt.Errorf("Error deleting image %s: %s", name, err.Error())
|
|
| 823 |
- } |
|
| 824 |
- if err := srv.runtime.repositories.Delete(name, tag, img.Id); err != nil {
|
|
| 825 |
- return err |
|
| 826 |
- } |
|
| 827 |
- } |
|
| 828 |
- return nil |
|
| 795 |
+ return srv.deleteImage(img, name, tag) |
|
| 829 | 796 |
} |
| 830 | 797 |
|
| 831 | 798 |
func (srv *Server) ImageGetCached(imgId string, config *Config) (*Image, error) {
|
| ... | ... |
@@ -110,7 +110,27 @@ func (store *TagStore) ImageName(id string) string {
|
| 110 | 110 |
return utils.TruncateId(id) |
| 111 | 111 |
} |
| 112 | 112 |
|
| 113 |
-func (store *TagStore) Delete(repoName, tag, imageName string) error {
|
|
| 113 |
+func (store *TagStore) DeleteAll(id string) error {
|
|
| 114 |
+ names, exists := store.ById()[id] |
|
| 115 |
+ if !exists || len(names) == 0 {
|
|
| 116 |
+ return nil |
|
| 117 |
+ } |
|
| 118 |
+ for _, name := range names {
|
|
| 119 |
+ if strings.Contains(name, ":") {
|
|
| 120 |
+ nameParts := strings.Split(name, ":") |
|
| 121 |
+ if err := store.Delete(nameParts[0], nameParts[1]); err != nil {
|
|
| 122 |
+ return err |
|
| 123 |
+ } |
|
| 124 |
+ } else {
|
|
| 125 |
+ if err := store.Delete(name, ""); err != nil {
|
|
| 126 |
+ return err |
|
| 127 |
+ } |
|
| 128 |
+ } |
|
| 129 |
+ } |
|
| 130 |
+ return nil |
|
| 131 |
+} |
|
| 132 |
+ |
|
| 133 |
+func (store *TagStore) Delete(repoName, tag string) error {
|
|
| 114 | 134 |
if err := store.Reload(); err != nil {
|
| 115 | 135 |
return err |
| 116 | 136 |
} |