Description: add compression feature 
 loongker-ce (5:20.10.3-21) buster; urgency=low
   * Version: 20.10.3-22
   * add compression feature 
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-10-08

--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/VERSION
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/VERSION
@@ -1 +1 @@
-20.10.3-21
+20.10.3-22
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/cli/cli/command/image/save.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/cli/cli/command/image/save.go
@@ -3,6 +3,7 @@ package image
 import (
 	"context"
 	"io"
+	"strings"
 
 	"github.com/docker/cli/cli"
 	"github.com/docker/cli/cli/command"
@@ -13,6 +14,7 @@ import (
 type saveOptions struct {
 	images []string
 	output string
+	compress string
 }
 
 // NewSaveCommand creates a new `docker save` command
@@ -32,10 +34,23 @@ func NewSaveCommand(dockerCli command.Cl
 	flags := cmd.Flags()
 
 	flags.StringVarP(&opts.output, "output", "o", "", "Write to a file, instead of STDOUT")
+	flags.StringVarP(&opts.compress, "compress", "c", "uncompressed", "specify a compress algo, gzip")
 
 	return cmd
 }
 
+func validateCompressAlgo(algo string) error {
+	switch algo {
+	case "uncompressed":
+	case "gzip":
+	case "xz": fallthrough
+	case "bzip2": fallthrough
+	default:
+		return errors.New("unsupported compress algo")
+	}
+	return nil
+}
+
 // RunSave performs a save against the engine based on the specified options
 func RunSave(dockerCli command.Cli, opts saveOptions) error {
 	if opts.output == "" && dockerCli.Out().IsTerminal() {
@@ -46,7 +61,12 @@ func RunSave(dockerCli command.Cli, opts
 		return errors.Wrap(err, "failed to save image")
 	}
 
-	responseBody, err := dockerCli.Client().ImageSave(context.Background(), opts.images)
+	var a = strings.ToLower(opts.compress)
+	if err := validateCompressAlgo(a); err !=nil {
+		return err
+	}
+
+	responseBody, err := dockerCli.Client().ImageSave(context.Background(), opts.images, a)
 	if err != nil {
 		return err
 	}
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/cli/cli/command/image/saveapp.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/cli/cli/command/image/saveapp.go
@@ -3,6 +3,7 @@ package image
 import (
 	"context"
 	"io"
+	"strings"
 
 	"github.com/docker/cli/cli"
 	"github.com/docker/cli/cli/command"
@@ -13,6 +14,7 @@ import (
 type saveAppOptions struct {
 	output string
 	applayer string
+	compress string
 }
 
 // NewSaveAppCommand creates a new `docker saveapp` command
@@ -32,6 +34,7 @@ func NewSaveAppCommand(dockerCli command
 
 	flags.StringVarP(&opts.output, "output", "o", "", "Write to a file, instead of STDOUT")
 	flags.StringVarP(&opts.applayer, "applayer", "a", "", "applayerid or applayername to save")
+	flags.StringVarP(&opts.compress, "compress", "c", "uncompressed", "specify a compress method, gzip")
 
 	return cmd
 }
@@ -49,8 +52,12 @@ func RunSaveApp(dockerCli command.Cli, o
 	if err := command.ValidateOutputPath(opts.output); err != nil {
 		return errors.Wrap(err, "failed to save applayer")
 	}
+	var a = strings.ToLower(opts.compress)
+	if err := validateCompressAlgo(a); err !=nil {
+		return err
+	}
 
-	responseBody, err := dockerCli.Client().AppSave(context.Background(), opts.applayer)
+	responseBody, err := dockerCli.Client().AppSave(context.Background(), opts.applayer, a)
 	if err != nil {
 		return err
 	}
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/cli/cli/command/image/saveupgrade.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/cli/cli/command/image/saveupgrade.go
@@ -3,6 +3,7 @@ package image
 import (
 	"context"
 	"io"
+	"strings"
 
 	"github.com/docker/cli/cli"
 	"github.com/docker/cli/cli/command"
@@ -15,6 +16,7 @@ type saveUpgradeOptions struct {
 	upgradeimage string
 	baseimage string
 	target string
+	compress string
 }
 
 // NewSaveCommand creates a new `docker save` command
@@ -36,6 +38,7 @@ func NewSaveUpgradeCommand(dockerCli com
 	flags.StringVarP(&opts.upgradeimage, "upgradeimage", "a", "", "the upgrade image to save")
 	flags.StringVarP(&opts.baseimage, "baseimage", "b", "", "base image of the upgrade image")
 	flags.StringVarP(&opts.target, "target", "t", "", "name of the target image")
+	flags.StringVarP(&opts.compress, "compress", "c", "uncompressed", "specify a compress algo, gzip")
 
 	return cmd
 }
@@ -62,7 +65,12 @@ func RunSaveUpgrade(dockerCli command.Cl
 		return errors.Wrap(err, "failed to save image")
 	}
 
-	responseBody, err := dockerCli.Client().UpgradeImageSave(context.Background(), opts.baseimage, opts.upgradeimage, opts.target)
+	var a = strings.ToLower(opts.compress)
+	if err := validateCompressAlgo(a); err !=nil {
+		return err
+	}
+
+	responseBody, err := dockerCli.Client().UpgradeImageSave(context.Background(), opts.baseimage, opts.upgradeimage, opts.target, a)
 	if err != nil {
 		return err
 	}
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/cli/vendor/github.com/docker/docker/client/app_save.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/cli/vendor/github.com/docker/docker/client/app_save.go
@@ -8,12 +8,16 @@ import (
 
 // AppSave retrieves one applayer from the docker host as an io.ReadCloser.
 // It's up to the caller to store the applayer and close the stream.
-func (cli *Client) AppSave(ctx context.Context, idorName string) (io.ReadCloser, error) {
+func (cli *Client) AppSave(ctx context.Context, idorName string, compress string) (io.ReadCloser, error) {
 	query := url.Values{}
 	if idorName != "" {
 		query.Set("name", idorName)
 	}
 
+	if compress != "" {
+		query.Set("compress", compress)
+	}
+
 	resp, err := cli.get(ctx, "/applayers/getapp", query, nil)
 	if err != nil {
 		return nil, err
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/cli/vendor/github.com/docker/docker/client/image_save.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/cli/vendor/github.com/docker/docker/client/image_save.go
@@ -8,9 +8,13 @@ import (
 
 // ImageSave retrieves one or more images from the docker host as an io.ReadCloser.
 // It's up to the caller to store the images and close the stream.
-func (cli *Client) ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) {
+func (cli *Client) ImageSave(ctx context.Context, imageIDs []string, compress string) (io.ReadCloser, error) {
+	var c []string
+
+	c = append(c, compress)
 	query := url.Values{
 		"names": imageIDs,
+		"compress": c,
 	}
 
 	resp, err := cli.get(ctx, "/images/get", query, nil)
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/cli/vendor/github.com/docker/docker/client/interface.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/cli/vendor/github.com/docker/docker/client/interface.go
@@ -101,15 +101,15 @@ type ImageAPIClient interface {
 	ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error)
 	ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error)
 	ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
-	ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
-	UpgradeImageSave(ctx context.Context, baseimage string, upgradeimage string, target string) (io.ReadCloser, error)
+	ImageSave(ctx context.Context, images []string, compress string) (io.ReadCloser, error)
+	UpgradeImageSave(ctx context.Context, baseimage string, upgradeimage string, target string, compress string) (io.ReadCloser, error)
 	ImageTag(ctx context.Context, image, ref string) error
 	ImagesPrune(ctx context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error)
 	ImageGenApplayer(ctx context.Context, imageID string, target string, quiet bool) (types.ImageLoadResponse, error)
 	AppLayerList(ctx context.Context, options types.AppLayerListOptions) ([]types.AppLayer, error)
 	ApplayerRemove(ctx context.Context,  idorName string) (types.AppLayerDeleteResponse, error)
 	Appcompose(ctx context.Context) error
-	AppSave(ctx context.Context, idorName string) (io.ReadCloser, error)
+	AppSave(ctx context.Context, idorName string, compress string) (io.ReadCloser, error)
 	AppLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error)
 	ApplayerRename(ctx context.Context, oldName, newName string) error
 }
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/cli/vendor/github.com/docker/docker/client/upgradeimage_save.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/cli/vendor/github.com/docker/docker/client/upgradeimage_save.go
@@ -10,7 +10,7 @@ import (
 
 // UpgradeImageSave retrieves one or more images from the docker host as an io.ReadCloser.
 // It's up to the caller to store the images and close the stream.
-func (cli *Client) UpgradeImageSave(ctx context.Context, baseimage string, upgradeimage string, target string) (io.ReadCloser, error) {
+func (cli *Client) UpgradeImageSave(ctx context.Context, baseimage string, upgradeimage string, target string, compress string) (io.ReadCloser, error) {
 	query := url.Values{}
 	if baseimage != "" {
 		query.Set("baseimage", baseimage)
@@ -18,6 +18,9 @@ func (cli *Client) UpgradeImageSave(ctx
 	if upgradeimage != "" {
 		query.Set("upgradeimage", upgradeimage)
 	}
+	if compress != "" {
+		query.Set("compress", compress)
+	}
 	ref, err := reference.ParseNormalizedNamed(target)
 	if err != nil {
 		return nil, errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", target)
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/engine/api/server/router/image/backend.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/engine/api/server/router/image/backend.go
@@ -36,11 +36,11 @@ type imageBackend interface {
 type importExportBackend interface {
 	LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
 	ImportImage(src string, repository, platform string, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
-	ExportImage(names []string, outStream io.Writer) error
+	ExportImage(names []string, outStream io.Writer, compress string) error
 	LoadUpgrade(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
-	ExportUpgrade(baseimage string, upgradeimage string, repo string, tag string, outStream io.Writer) error
+	ExportUpgrade(baseimage string, upgradeimage string, repo string, tag string, outStream io.Writer, compress string) error
 	LoadApp(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
-	ExportApp(idorName string, outStream io.Writer) error
+	ExportApp(idorName string, outStream io.Writer, compress string) error
 }
 
 type registryBackend interface {
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/engine/api/server/router/image/image_routes.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/engine/api/server/router/image/image_routes.go
@@ -151,13 +151,15 @@ func (s *imageRouter) getImagesGet(ctx c
 	output := ioutils.NewWriteFlusher(w)
 	defer output.Close()
 	var names []string
+	var methods []string
 	if name, ok := vars["name"]; ok {
 		names = []string{name}
 	} else {
 		names = r.Form["names"]
 	}
+	methods = r.Form["compress"]
 
-	if err := s.backend.ExportImage(names, output); err != nil {
+	if err := s.backend.ExportImage(names, output, methods[0]); err != nil {
 		if !output.Flushed() {
 			return err
 		}
@@ -176,9 +178,11 @@ func (s *imageRouter) getAppGet(ctx cont
 	output := ioutils.NewWriteFlusher(w)
 	defer output.Close()
 	var names []string
+	var compress []string
 	names = r.Form["name"]
+	compress = r.Form["compress"]
 
-	if err := s.backend.ExportApp(names[0], output); err != nil {
+	if err := s.backend.ExportApp(names[0], output, compress[0]); err != nil {
 		if !output.Flushed() {
 			return err
 		}
@@ -251,13 +255,15 @@ func (s *imageRouter) getUpgradeImageGet
 	var upgradenames []string
 	var repos []string
 	var tags []string
+	var compress []string
 
 	basenames = r.Form["baseimage"]
 	upgradenames = r.Form["upgradeimage"]
 	repos = r.Form["repo"]
 	tags = r.Form["tag"]
+	compress = r.Form["compress"]
 
-	if err := s.backend.ExportUpgrade(basenames[0], upgradenames[0], repos[0], tags[0], output); err != nil {
+	if err := s.backend.ExportUpgrade(basenames[0], upgradenames[0], repos[0], tags[0], output, compress[0]); err != nil {
 		if !output.Flushed() {
 			return err
 		}
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/engine/daemon/images/image_exporter.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/engine/daemon/images/image_exporter.go
@@ -12,9 +12,9 @@ import (
 // stream. All images with the given tag and all versions containing
 // the same tag are exported. names is the set of tags to export, and
 // outStream is the writer which the images are written to.
-func (i *ImageService) ExportImage(names []string, outStream io.Writer) error {
+func (i *ImageService) ExportImage(names []string, outStream io.Writer, compress string) error {
 	imageExporter := tarexport.NewTarExporter(i.imageStore, i.layerStores, i.referenceStore, i.applayerStore, i)
-	return imageExporter.Save(names, outStream)
+	return imageExporter.Save(names, outStream, compress)
 }
 
 // LoadImage uploads a set of images into the repository. This is the
@@ -30,9 +30,9 @@ func (i *ImageService) LoadUpgrade(inTar
 	return imageExporter.LoadUpgrade(inTar, outStream, quiet)
 }
 
-func (i *ImageService) ExportUpgrade(baseimage string, upgradeimage string, repo string, tag string, outStream io.Writer) error {
+func (i *ImageService) ExportUpgrade(baseimage string, upgradeimage string, repo string, tag string, outStream io.Writer, compress string) error {
 	imageExporter := tarexport.NewTarExporter(i.imageStore, i.layerStores, i.referenceStore, i.applayerStore, i)
-	return imageExporter.SaveUpgrade(baseimage, upgradeimage, repo, tag, outStream)
+	return imageExporter.SaveUpgrade(baseimage, upgradeimage, repo, tag, outStream, compress)
 }
 
 func (i *ImageService) LoadApp(inTar io.ReadCloser, outStream io.Writer, quiet bool) error {
@@ -40,7 +40,7 @@ func (i *ImageService) LoadApp(inTar io.
 	return appExporter.LoadApp(inTar, outStream, quiet)
 }
 
-func (i *ImageService) ExportApp(idorName string, outStream io.Writer) error {
+func (i *ImageService) ExportApp(idorName string, outStream io.Writer, compress string) error {
 	appExporter := apptarexport.NewAppTarExporter(i.imageStore, i.layerStores, i.applayerStore, i.referenceStore, i)
-	return appExporter.SaveApp(idorName, outStream)
+	return appExporter.SaveApp(idorName, outStream, compress)
 }
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/engine/image/apptarexport/appsave.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/engine/image/apptarexport/appsave.go
@@ -4,11 +4,21 @@ import (
 	"io"
 	"io/ioutil"
 	"os"
-
+	"fmt"
 	"github.com/docker/docker/pkg/archive"
 )
 
-func (l *apptarexporter) SaveApp(idorName string, outStream io.Writer) error {
+func (l *apptarexporter) SaveApp(idorName string, outStream io.Writer, compress string) error {
+
+	var c archive.Compression
+	switch compress {
+	case "uncompressed":
+		c = archive.Uncompressed
+	case "gzip":
+		c = archive.Gzip
+	default:
+		return fmt.Errorf("Unsupported compress algo")
+	}
 
 	id, err := l.as.Search(idorName)
 	if err != nil {
@@ -27,7 +37,7 @@ func (l *apptarexporter) SaveApp(idorNam
 	if err != nil {
 		return err
 	}
-	fs, err := archive.Tar(tempDir, archive.Uncompressed)
+	fs, err := archive.Tar(tempDir, c)
 	if err != nil {
 		return err
 	}
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/engine/image/image.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/engine/image/image.go
@@ -525,15 +525,15 @@ func NewHistory(author, comment, created
 type Exporter interface {
 	Load(io.ReadCloser, io.Writer, bool) error
 	// TODO: Load(net.Context, io.ReadCloser, <- chan StatusMessage) error
-	Save([]string, io.Writer) error
+	Save([]string, io.Writer, string) error
 	LoadUpgrade(io.ReadCloser, io.Writer, bool) error
-	SaveUpgrade(string, string, string, string, io.Writer) error
+	SaveUpgrade(string, string, string, string, io.Writer, string) error
 }
 
 // AppExporter provides interface for loading and saving images
 type AppExporter interface {
 	LoadApp(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
-	SaveApp(idorName string, outStream io.Writer) error
+	SaveApp(idorName string, outStream io.Writer, compress string) error
 }
 
 // NewFromJSON creates an Image configuration from json.
--- lcf-utils-1.0.1/src/loongker-ce-20.10.3.orig/sources/engine/image/tarexport/save.go
+++ lcf-utils-1.0.1/src/loongker-ce-20.10.3/sources/engine/image/tarexport/save.go
@@ -35,6 +35,7 @@ type saveSession struct {
 	images      map[image.ID]*imageDescriptor
 	savedLayers map[string]struct{}
 	diffIDPaths map[layer.DiffID]string // cache every diffID blob to avoid duplicates
+	compress    string
 }
 
 type saveUpgradeSession struct {
@@ -47,9 +48,10 @@ type saveUpgradeSession struct {
 	baseID      image.ID
 	upgradeID   image.ID
 	index       int
+	compress    string
 }
 
-func (l *tarexporter) SaveUpgrade(basename string, upgradename string, repo string, tag string, outStream io.Writer) error {
+func (l *tarexporter) SaveUpgrade(basename string, upgradename string, repo string, tag string, outStream io.Writer, compress string) error {
 	var pbase *imageDescriptor
 	var pupgrade  *imageDescriptor
 	var baseID image.ID
@@ -76,7 +78,7 @@ func (l *tarexporter) SaveUpgrade(basena
 		pupgrade = v
 		break
 	}
-	session1 := &saveUpgradeSession{tarexporter:l, baseimgDescr: pbase, upgradeimgDescr: pupgrade, baseID:baseID, index:-1}
+	session1 := &saveUpgradeSession{tarexporter:l, baseimgDescr: pbase, upgradeimgDescr: pupgrade, baseID:baseID, index:-1, compress: compress}
 
 	have := session1.checkUpgradeIncludebase(pbase, pupgrade)
 
@@ -87,15 +89,14 @@ func (l *tarexporter) SaveUpgrade(basena
 	return session1.saveUpgrade(outStream, repo, tag)
 }
 
-func (l *tarexporter) Save(names []string, outStream io.Writer) error {
+func (l *tarexporter) Save(names []string, outStream io.Writer, compress string) error {
 	images, err := l.parseNames(names)
 	if err != nil {
 		return err
 	}
-
 	// Release all the image top layer references
 	defer l.releaseLayerReferences(images)
-	return (&saveSession{tarexporter: l, images: images}).save(outStream)
+	return (&saveSession{tarexporter: l, images: images, compress: compress}).save(outStream)
 }
 
 func (s *saveUpgradeSession) checkUpgradeIncludebase(pbase *imageDescriptor, pupgrade *imageDescriptor) bool {
@@ -122,6 +123,16 @@ func (s *saveUpgradeSession) saveUpgrade
 	s.savedLayers = make(map[string]struct{})
 	s.diffIDPaths = make(map[layer.DiffID]string)
 
+	var c archive.Compression
+	switch s.compress {
+	case "uncompressed":
+		c = archive.Uncompressed
+	case "gzip":
+		c = archive.Gzip
+	default:
+		return fmt.Errorf("Unsupported compress algo")
+	}
+
 	// get image json
 	tempDir, err := ioutil.TempDir("", "docker-export-")
 	if err != nil {
@@ -198,7 +209,7 @@ func (s *saveUpgradeSession) saveUpgrade
 		return err
 	}
 
-	fs, err := archive.Tar(tempDir, archive.Uncompressed)
+	fs, err := archive.Tar(tempDir, c)
 	if err != nil {
 		return err
 	}
@@ -424,6 +435,16 @@ func (s *saveSession) save(outStream io.
 	s.savedLayers = make(map[string]struct{})
 	s.diffIDPaths = make(map[layer.DiffID]string)
 
+	var c archive.Compression
+	switch s.compress {
+	case "uncompressed":
+		c = archive.Uncompressed
+	case "gzip":
+		c = archive.Gzip
+	default:
+		return fmt.Errorf("Unsupported compress algo")
+	}
+
 	// get image json
 	tempDir, err := ioutil.TempDir("", "docker-export-")
 	if err != nil {
@@ -516,8 +537,7 @@ func (s *saveSession) save(outStream io.
 	if err := system.Chtimes(manifestFileName, time.Unix(0, 0), time.Unix(0, 0)); err != nil {
 		return err
 	}
-
-	fs, err := archive.Tar(tempDir, archive.Uncompressed)
+	fs, err := archive.Tar(tempDir, c)
 	if err != nil {
 		return err
 	}
