Merge pull request #65 from nalind/diffoptions

Make Diff() methods take an optional *DiffOptions
This commit is contained in:
Daniel J Walsh 2017-06-19 11:50:54 -04:00 committed by GitHub
commit d46b0bfb28
4 changed files with 55 additions and 35 deletions

View File

@ -12,11 +12,12 @@ import (
) )
var ( var (
applyDiffFile = "" applyDiffFile = ""
diffFile = "" diffFile = ""
diffGzip = false diffUncompressed = false
diffBzip2 = false diffGzip = false
diffXz = false diffBzip2 = false
diffXz = false
) )
func changes(flags *mflag.FlagSet, action string, m storage.Store, args []string) int { func changes(flags *mflag.FlagSet, action string, m storage.Store, args []string) int {
@ -71,28 +72,27 @@ func diff(flags *mflag.FlagSet, action string, m storage.Store, args []string) i
diffStream = f diffStream = f
defer f.Close() defer f.Close()
} }
reader, err := m.Diff(from, to)
options := storage.DiffOptions{}
if diffUncompressed || diffGzip || diffBzip2 || diffXz {
c := archive.Uncompressed
if diffGzip {
c = archive.Gzip
}
if diffBzip2 {
c = archive.Bzip2
}
if diffXz {
c = archive.Xz
}
options.Compression = &c
}
reader, err := m.Diff(from, to, &options)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err) fmt.Fprintf(os.Stderr, "%v\n", err)
return 1 return 1
} }
if diffGzip || diffBzip2 || diffXz {
compression := archive.Uncompressed
if diffGzip {
compression = archive.Gzip
} else if diffBzip2 {
compression = archive.Bzip2
} else if diffXz {
compression = archive.Xz
}
compressor, err := archive.CompressStream(diffStream, compression)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
return 1
}
diffStream = compressor
defer compressor.Close()
}
_, err = io.Copy(diffStream, reader) _, err = io.Copy(diffStream, reader)
reader.Close() reader.Close()
if err != nil { if err != nil {
@ -171,9 +171,10 @@ func init() {
action: diff, action: diff,
addFlags: func(flags *mflag.FlagSet, cmd *command) { addFlags: func(flags *mflag.FlagSet, cmd *command) {
flags.StringVar(&diffFile, []string{"-file", "f"}, "", "Write to file instead of stdout") flags.StringVar(&diffFile, []string{"-file", "f"}, "", "Write to file instead of stdout")
flags.BoolVar(&diffUncompressed, []string{"-uncompressed", "u"}, diffUncompressed, "Use no compression")
flags.BoolVar(&diffGzip, []string{"-gzip", "c"}, diffGzip, "Compress using gzip") flags.BoolVar(&diffGzip, []string{"-gzip", "c"}, diffGzip, "Compress using gzip")
flags.BoolVar(&diffBzip2, []string{"-bzip2", "-bz2", "b"}, diffBzip2, "Compress using bzip2") flags.BoolVar(&diffBzip2, []string{"-bzip2", "-bz2", "b"}, diffBzip2, "Compress using bzip2 (not currently supported)")
flags.BoolVar(&diffXz, []string{"-xz", "x"}, diffXz, "Compress using xz") flags.BoolVar(&diffXz, []string{"-xz", "x"}, diffXz, "Compress using xz (not currently supported)")
}, },
}) })
commands = append(commands, command{ commands = append(commands, command{

View File

@ -19,9 +19,14 @@ Write the diff to the specified file instead of stdout.
**-c | --gzip** **-c | --gzip**
Compress the diff using gzip compression. If the layer was populated by a Force the diff to be compressed using gzip compression. If the layer was
layer diff, and that layer diff was compressed, this will be done populated by a layer diff, and that layer diff was compressed, this will be
automatically. done automatically.
**-u | --uncompressed**
Force the diff to be uncompressed. If the layer was populated by a layer diff,
and that layer diff was compressed, it will be decompressed for output.
## EXAMPLE ## EXAMPLE
**oci-storage diff my-base-layer** **oci-storage diff my-base-layer**

View File

@ -81,6 +81,12 @@ type layerMountPoint struct {
MountCount int `json:"count"` MountCount int `json:"count"`
} }
// DiffOptions override the default behavior of Diff() methods.
type DiffOptions struct {
// Compression, if set overrides the default compressor when generating a diff.
Compression *archive.Compression
}
// ROLayerStore wraps a graph driver, adding the ability to refer to layers by // ROLayerStore wraps a graph driver, adding the ability to refer to layers by
// name, and keeping track of parent-child relationships, along with a list of // name, and keeping track of parent-child relationships, along with a list of
// all known layers. // all known layers.
@ -107,8 +113,9 @@ type ROLayerStore interface {
// Diff produces a tarstream which can be applied to a layer with the contents // Diff produces a tarstream which can be applied to a layer with the contents
// of the first layer to produce a layer with the contents of the second layer. // of the first layer to produce a layer with the contents of the second layer.
// By default, the parent of the second layer is used as the first // By default, the parent of the second layer is used as the first
// layer, so it need not be specified. // layer, so it need not be specified. Options can be used to override
Diff(from, to string) (io.ReadCloser, error) // default behavior, but are also not required.
Diff(from, to string, options *DiffOptions) (io.ReadCloser, error)
// DiffSize produces an estimate of the length of the tarstream which would be // DiffSize produces an estimate of the length of the tarstream which would be
// produced by Diff. // produced by Diff.
@ -741,13 +748,15 @@ func (r *layerStore) newFileGetter(id string) (drivers.FileGetCloser, error) {
}, nil }, nil
} }
func (r *layerStore) Diff(from, to string) (io.ReadCloser, error) { func (r *layerStore) Diff(from, to string, options *DiffOptions) (io.ReadCloser, error) {
var metadata storage.Unpacker var metadata storage.Unpacker
from, to, toLayer, err := r.findParentAndLayer(from, to) from, to, toLayer, err := r.findParentAndLayer(from, to)
if err != nil { if err != nil {
return nil, ErrLayerUnknown return nil, ErrLayerUnknown
} }
// Default to applying the type of encryption that we noted was used
// for the layerdiff when it was applied.
compression := archive.Uncompressed compression := archive.Uncompressed
if cflag, ok := toLayer.Flags[compressionFlag]; ok { if cflag, ok := toLayer.Flags[compressionFlag]; ok {
if ctype, ok := cflag.(float64); ok { if ctype, ok := cflag.(float64); ok {
@ -756,6 +765,11 @@ func (r *layerStore) Diff(from, to string) (io.ReadCloser, error) {
compression = archive.Compression(ctype) compression = archive.Compression(ctype)
} }
} }
// If a particular compression type (or no compression) was selected,
// use that instead.
if options != nil && options.Compression != nil {
compression = *options.Compression
}
if from != toLayer.Parent { if from != toLayer.Parent {
diff, err := r.driver.Diff(to, from) diff, err := r.driver.Diff(to, from)
if err == nil && (compression != archive.Uncompressed) { if err == nil && (compression != archive.Uncompressed) {

View File

@ -298,8 +298,8 @@ type Store interface {
DiffSize(from, to string) (int64, error) DiffSize(from, to string) (int64, error)
// Diff returns the tarstream which would specify the changes returned by // Diff returns the tarstream which would specify the changes returned by
// Changes. // Changes. If options are passed in, they can override default behaviors.
Diff(from, to string) (io.ReadCloser, error) Diff(from, to string, options *DiffOptions) (io.ReadCloser, error)
// ApplyDiff applies a tarstream to a layer. Information about the tarstream // ApplyDiff applies a tarstream to a layer. Information about the tarstream
// is cached with the layer. Typically, a layer which is populated using a // is cached with the layer. Typically, a layer which is populated using a
@ -1747,7 +1747,7 @@ func (s *store) DiffSize(from, to string) (int64, error) {
return -1, ErrLayerUnknown return -1, ErrLayerUnknown
} }
func (s *store) Diff(from, to string) (io.ReadCloser, error) { func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, error) {
rlstore, err := s.LayerStore() rlstore, err := s.LayerStore()
if err != nil { if err != nil {
return nil, err return nil, err
@ -1764,7 +1764,7 @@ func (s *store) Diff(from, to string) (io.ReadCloser, error) {
rlstore.Load() rlstore.Load()
} }
if rlstore.Exists(to) { if rlstore.Exists(to) {
return rlstore.Diff(from, to) return rlstore.Diff(from, to, options)
} }
} }
return nil, ErrLayerUnknown return nil, ErrLayerUnknown