Browse code

Implement fallback operation for driver.Diff()

This moves the Diff() operation to a separate Differ interface and
implements a fallback that uses the Changes() results to encode
a diff tar.

Alexander Larsson authored on 2013/11/12 00:47:36
Showing 5 changed files
... ...
@@ -1382,7 +1382,8 @@ func (container *Container) ExportRw() (archive.Archive, error) {
1382 1382
 	if container.runtime == nil {
1383 1383
 		return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
1384 1384
 	}
1385
-	return container.runtime.driver.Diff(container.ID)
1385
+
1386
+	return container.runtime.Diff(container)
1386 1387
 }
1387 1388
 
1388 1389
 func (container *Container) Export() (archive.Archive, error) {
... ...
@@ -2,7 +2,6 @@ package devmapper
2 2
 
3 3
 import (
4 4
 	"fmt"
5
-	"github.com/dotcloud/docker/archive"
6 5
 	"github.com/dotcloud/docker/graphdriver"
7 6
 	"os"
8 7
 	"path"
... ...
@@ -57,10 +56,6 @@ func (d *Driver) Get(id string) (string, error) {
57 57
 	return mp, nil
58 58
 }
59 59
 
60
-func (d *Driver) Diff(id string) (archive.Archive, error) {
61
-	return nil, fmt.Errorf("Not implemented")
62
-}
63
-
64 60
 func (d *Driver) DiffSize(id string) (int64, error) {
65 61
 	return -1, fmt.Errorf("Not implemented")
66 62
 }
... ...
@@ -16,7 +16,6 @@ type Driver interface {
16 16
 
17 17
 	Get(id string) (dir string, err error)
18 18
 
19
-	Diff(id string) (archive.Archive, error)
20 19
 	DiffSize(id string) (bytes int64, err error)
21 20
 
22 21
 	Cleanup() error
... ...
@@ -26,6 +25,10 @@ type Changer interface {
26 26
 	Changes(id string) ([]archive.Change, error)
27 27
 }
28 28
 
29
+type Differ interface {
30
+	Diff(id string) (archive.Archive, error)
31
+}
32
+
29 33
 var (
30 34
 	// All registred drivers
31 35
 	drivers map[string]InitFunc
... ...
@@ -73,14 +73,6 @@ func (d *Driver) Get(id string) (string, error) {
73 73
 	return dir, nil
74 74
 }
75 75
 
76
-func (d *Driver) Diff(id string) (archive.Archive, error) {
77
-	p, err := d.Get(id)
78
-	if err != nil {
79
-		return nil, err
80
-	}
81
-	return archive.Tar(p, archive.Uncompressed)
82
-}
83
-
84 76
 func (d *Driver) DiffSize(id string) (int64, error) {
85 77
 	return -1, fmt.Errorf("Not implemented")
86 78
 }
... ...
@@ -18,6 +18,7 @@ import (
18 18
 	"os"
19 19
 	"os/exec"
20 20
 	"path"
21
+	"path/filepath"
21 22
 	"sort"
22 23
 	"strings"
23 24
 	"time"
... ...
@@ -747,6 +748,37 @@ func (runtime *Runtime) Changes(container *Container) ([]archive.Change, error)
747 747
 	return archive.ChangesDirs(cDir, initDir)
748 748
 }
749 749
 
750
+func (runtime *Runtime) Diff(container *Container) (archive.Archive, error) {
751
+	if differ, ok := runtime.driver.(graphdriver.Differ); ok {
752
+		return differ.Diff(container.ID)
753
+	}
754
+
755
+	changes, err := runtime.Changes(container)
756
+	if err != nil {
757
+		return nil, err
758
+	}
759
+
760
+	cDir, err := runtime.driver.Get(container.ID)
761
+	if err != nil {
762
+		return nil, fmt.Errorf("Error getting container rootfs %s from driver %s: %s", container.ID, container.runtime.driver, err)
763
+	}
764
+
765
+	files := make([]string, 0)
766
+	deletions := make([]string, 0)
767
+	for _, change := range changes {
768
+		if change.Kind == archive.ChangeModify || change.Kind == archive.ChangeAdd {
769
+			files = append(files, change.Path)
770
+		}
771
+		if change.Kind == archive.ChangeDelete {
772
+			base := filepath.Base(change.Path)
773
+			dir := filepath.Dir(change.Path)
774
+			deletions = append(deletions, filepath.Join(dir, ".wh."+base))
775
+		}
776
+	}
777
+
778
+	return archive.TarFilter(cDir, archive.Uncompressed, files, false, deletions)
779
+}
780
+
750 781
 func linkLxcStart(root string) error {
751 782
 	sourcePath, err := exec.LookPath("lxc-start")
752 783
 	if err != nil {