Description: add appcompose 
 .
 docker-ce (5:20.10.3-12) buster; urgency=low
 .
   * Version: 20.10.3-12
   * add appcompose 
Author: wanghuaiqing <wanghuaiqing@loongson.com>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: 2022-05-06

--- /dev/null
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/engine/image/appcompose/appcompose.go
@@ -0,0 +1,181 @@
+package appcompose // import "github.com/docker/docker/image/appcompose"
+
+import (
+	"encoding/json"
+	"github.com/docker/docker/image"
+	"github.com/docker/docker/layer"
+	"github.com/sirupsen/logrus"
+	"github.com/docker/docker/pkg/stringid"
+	refstore "github.com/docker/docker/reference"
+	"github.com/docker/distribution/reference"
+)
+
+
+type appcomposer struct {
+	is             image.Store
+	lss            map[string]layer.Store
+	as	       image.ApplayerStore
+	rs             refstore.Store
+	loggerImgEvent image.LogImageEvent
+}
+type appComposer interface {
+	GenImgByApplayerID(applayerID image.ID) error
+	GenImgByImageID(ImageID image.ID) error
+	GenImg() error
+}
+
+// NewAppComposer returns new AppComposer for composing app images
+func NewAppComposer(is image.Store, lss map[string]layer.Store, rs refstore.Store, as image.ApplayerStore, loggerImgEvent image.LogImageEvent) appComposer {
+	return &appcomposer{
+		is:             is,
+		lss:            lss,
+		rs:             rs,
+		as:		as,
+		loggerImgEvent: loggerImgEvent,
+	}
+}
+
+
+func (ac *appcomposer) appcompose(imgid image.ID, baseimg *image.Image, al image.AppLayer) (err error) {
+	defer func() {
+		if err != nil {
+			logrus.Error("Error compose appimg between applayer: %v and img: %v for %v", al.AppLayerID(), baseimg.ID(), err)
+		}
+	}()
+	id := imgid.String()
+	applayerid := al.AppLayerID().String()
+	ac.is.LockId(id)
+	defer ac.is.UnlockId(id)
+	ac.as.LockId(applayerid)
+	defer ac.as.UnlockId(applayerid)
+	_, err = ac.is.Search(id)
+	if err != nil {
+		return nil
+	}
+	_, err = ac.as.Search(applayerid)
+	if err != nil {
+		return nil
+	}
+	deplen := al.Depslen()
+	deps := al.Deps()
+	if deplen > baseimg.DiffLen() {
+		logrus.Debugf("In func appcompose image %v have too few layer")
+		return nil
+	}
+	diffs := baseimg.Diff()
+	difflen := baseimg.DiffLen()
+	for i :=0; i < deplen; i++ {
+		if deps[i] != diffs[i] {
+			logrus.Debugf("In func appcompose diffID not match")
+			return nil
+		}
+	}
+	if deplen < difflen {
+		for i := deplen; i < difflen; i++ {
+			flag, err := baseimg.GetLayerDiff(diffs[i])
+			if err != nil {
+				return err
+			}
+			if flag != "true" {
+				return nil
+			}
+		}
+	}
+	chainid := baseimg.RootFS.ChainID()
+	datadir := ac.as.GetAppLayerDataDir(al.AppLayerID())
+	_, err = ac.lss[baseimg.OperatingSystem()].RegisterDir(datadir, al.DiffID(), al.Size(), chainid)
+	if err != nil {
+		return
+	}
+	topimg, err := ac.as.GetConfig(al.AppLayerID())
+	if err != nil {
+		return
+	}
+	mergeImage, err := image.NewMergeImage(baseimg, topimg)
+	if err != nil {
+		return
+	}
+	have, err := ac.is.GetAppImage(mergeImage)
+	if err != nil {
+		return
+	}
+	if true == have {
+		return  nil
+	}
+	config, err := json.Marshal(mergeImage)
+	if err != nil {
+		return
+	}
+	imgID, err := ac.is.Create(config)
+	if err != nil {
+		return
+	}
+	err = ac.as.AppendImgID(al.AppLayerID(), imgID)
+	if err != nil {
+		return
+	}
+	ac.loggerImgEvent.LogImageEvent(imgID.String(), imgID.String(), "Compose")
+	err = ac.is.AddAppImage(mergeImage)
+	if err != nil {
+		return
+	}
+	newTag, err := reference.ParseNormalizedNamed(al.Name())
+	if err != nil {
+		return
+	}
+	var baseID image.ID
+	baseID = baseimg.ID()
+	if newTag, err = reference.WithTag(reference.TrimNamed(newTag), stringid.TruncateID(baseID.String())); err != nil {
+		return
+	}
+	if err = ac.rs.AddTag(newTag, imgID.Digest(), true); err != nil {
+		return
+	}
+
+	if err = ac.is.SetLastUpdated(imgID); err != nil {
+		return
+	}
+	return
+}
+
+func (ac *appcomposer) GenImgByApplayerID(applayerID image.ID) error {
+	al, err := ac.as.Get(applayerID)
+	if err != nil {
+		return err
+	}
+
+	basemap := make(map[image.ID]*image.Image)
+	basemap = ac.is.Map()
+	for id, img := range basemap {
+		err = ac.appcompose(id, img, al)
+	}
+	return err
+}
+
+func (ac *appcomposer) GenImgByImageID(ImageID image.ID) error {
+	img, err := ac.is.Get(ImageID)
+	if err != nil {
+		return err
+	}
+	almap := make(map[image.ID]image.AppLayer)
+	almap = ac.as.Map()
+	for _, al := range almap {
+		err = ac.appcompose(ImageID, img, al)
+	}
+	return err
+}
+
+func (ac *appcomposer) GenImg() error {
+
+	basemap := make(map[image.ID]*image.Image)
+	almap := make(map[image.ID]image.AppLayer)
+	basemap = ac.is.Map()
+	almap = ac.as.Map()
+	var err error
+	for _, al := range almap {
+		for id, img := range basemap {
+			err = ac.appcompose(id, img, al)
+		}
+	}
+	return err
+}
