| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,208 @@ |
| 0 |
+package archive |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "os" |
|
| 5 |
+ "path/filepath" |
|
| 6 |
+ "strings" |
|
| 7 |
+ "syscall" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+type ChangeType int |
|
| 11 |
+ |
|
| 12 |
+const ( |
|
| 13 |
+ ChangeModify = iota |
|
| 14 |
+ ChangeAdd |
|
| 15 |
+ ChangeDelete |
|
| 16 |
+) |
|
| 17 |
+ |
|
| 18 |
+type Change struct {
|
|
| 19 |
+ Path string |
|
| 20 |
+ Kind ChangeType |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+func (change *Change) String() string {
|
|
| 24 |
+ var kind string |
|
| 25 |
+ switch change.Kind {
|
|
| 26 |
+ case ChangeModify: |
|
| 27 |
+ kind = "C" |
|
| 28 |
+ case ChangeAdd: |
|
| 29 |
+ kind = "A" |
|
| 30 |
+ case ChangeDelete: |
|
| 31 |
+ kind = "D" |
|
| 32 |
+ } |
|
| 33 |
+ return fmt.Sprintf("%s %s", kind, change.Path)
|
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+func Changes(layers []string, rw string) ([]Change, error) {
|
|
| 37 |
+ var changes []Change |
|
| 38 |
+ err := filepath.Walk(rw, func(path string, f os.FileInfo, err error) error {
|
|
| 39 |
+ if err != nil {
|
|
| 40 |
+ return err |
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ // Rebase path |
|
| 44 |
+ path, err = filepath.Rel(rw, path) |
|
| 45 |
+ if err != nil {
|
|
| 46 |
+ return err |
|
| 47 |
+ } |
|
| 48 |
+ path = filepath.Join("/", path)
|
|
| 49 |
+ |
|
| 50 |
+ // Skip root |
|
| 51 |
+ if path == "/" {
|
|
| 52 |
+ return nil |
|
| 53 |
+ } |
|
| 54 |
+ |
|
| 55 |
+ // Skip AUFS metadata |
|
| 56 |
+ if matched, err := filepath.Match("/.wh..wh.*", path); err != nil || matched {
|
|
| 57 |
+ return err |
|
| 58 |
+ } |
|
| 59 |
+ |
|
| 60 |
+ change := Change{
|
|
| 61 |
+ Path: path, |
|
| 62 |
+ } |
|
| 63 |
+ |
|
| 64 |
+ // Find out what kind of modification happened |
|
| 65 |
+ file := filepath.Base(path) |
|
| 66 |
+ // If there is a whiteout, then the file was removed |
|
| 67 |
+ if strings.HasPrefix(file, ".wh.") {
|
|
| 68 |
+ originalFile := file[len(".wh."):]
|
|
| 69 |
+ change.Path = filepath.Join(filepath.Dir(path), originalFile) |
|
| 70 |
+ change.Kind = ChangeDelete |
|
| 71 |
+ } else {
|
|
| 72 |
+ // Otherwise, the file was added |
|
| 73 |
+ change.Kind = ChangeAdd |
|
| 74 |
+ |
|
| 75 |
+ // ...Unless it already existed in a top layer, in which case, it's a modification |
|
| 76 |
+ for _, layer := range layers {
|
|
| 77 |
+ stat, err := os.Stat(filepath.Join(layer, path)) |
|
| 78 |
+ if err != nil && !os.IsNotExist(err) {
|
|
| 79 |
+ return err |
|
| 80 |
+ } |
|
| 81 |
+ if err == nil {
|
|
| 82 |
+ // The file existed in the top layer, so that's a modification |
|
| 83 |
+ |
|
| 84 |
+ // However, if it's a directory, maybe it wasn't actually modified. |
|
| 85 |
+ // If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar |
|
| 86 |
+ if stat.IsDir() && f.IsDir() {
|
|
| 87 |
+ if f.Size() == stat.Size() && f.Mode() == stat.Mode() && f.ModTime() == stat.ModTime() {
|
|
| 88 |
+ // Both directories are the same, don't record the change |
|
| 89 |
+ return nil |
|
| 90 |
+ } |
|
| 91 |
+ } |
|
| 92 |
+ change.Kind = ChangeModify |
|
| 93 |
+ break |
|
| 94 |
+ } |
|
| 95 |
+ } |
|
| 96 |
+ } |
|
| 97 |
+ |
|
| 98 |
+ // Record change |
|
| 99 |
+ changes = append(changes, change) |
|
| 100 |
+ return nil |
|
| 101 |
+ }) |
|
| 102 |
+ if err != nil && !os.IsNotExist(err) {
|
|
| 103 |
+ return nil, err |
|
| 104 |
+ } |
|
| 105 |
+ return changes, nil |
|
| 106 |
+} |
|
| 107 |
+ |
|
| 108 |
+func ChangesDirs(newDir, oldDir string) ([]Change, error) {
|
|
| 109 |
+ var changes []Change |
|
| 110 |
+ err := filepath.Walk(newDir, func(newPath string, f os.FileInfo, err error) error {
|
|
| 111 |
+ if err != nil {
|
|
| 112 |
+ return err |
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ var newStat syscall.Stat_t |
|
| 116 |
+ err = syscall.Lstat(newPath, &newStat) |
|
| 117 |
+ if err != nil {
|
|
| 118 |
+ return err |
|
| 119 |
+ } |
|
| 120 |
+ |
|
| 121 |
+ // Rebase path |
|
| 122 |
+ relPath, err := filepath.Rel(newDir, newPath) |
|
| 123 |
+ if err != nil {
|
|
| 124 |
+ return err |
|
| 125 |
+ } |
|
| 126 |
+ relPath = filepath.Join("/", relPath)
|
|
| 127 |
+ |
|
| 128 |
+ // Skip root |
|
| 129 |
+ if relPath == "/" || relPath == "/.docker-id" {
|
|
| 130 |
+ return nil |
|
| 131 |
+ } |
|
| 132 |
+ |
|
| 133 |
+ change := Change{
|
|
| 134 |
+ Path: relPath, |
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ oldPath := filepath.Join(oldDir, relPath) |
|
| 138 |
+ |
|
| 139 |
+ var oldStat = &syscall.Stat_t{}
|
|
| 140 |
+ err = syscall.Lstat(oldPath, oldStat) |
|
| 141 |
+ if err != nil {
|
|
| 142 |
+ if !os.IsNotExist(err) {
|
|
| 143 |
+ return err |
|
| 144 |
+ } |
|
| 145 |
+ oldStat = nil |
|
| 146 |
+ } |
|
| 147 |
+ |
|
| 148 |
+ if oldStat == nil {
|
|
| 149 |
+ change.Kind = ChangeAdd |
|
| 150 |
+ changes = append(changes, change) |
|
| 151 |
+ } else {
|
|
| 152 |
+ if oldStat.Ino != newStat.Ino || |
|
| 153 |
+ oldStat.Mode != newStat.Mode || |
|
| 154 |
+ oldStat.Uid != newStat.Uid || |
|
| 155 |
+ oldStat.Gid != newStat.Gid || |
|
| 156 |
+ oldStat.Rdev != newStat.Rdev || |
|
| 157 |
+ oldStat.Size != newStat.Size || |
|
| 158 |
+ oldStat.Blocks != newStat.Blocks || |
|
| 159 |
+ oldStat.Mtim != newStat.Mtim || |
|
| 160 |
+ oldStat.Ctim != newStat.Ctim {
|
|
| 161 |
+ change.Kind = ChangeModify |
|
| 162 |
+ changes = append(changes, change) |
|
| 163 |
+ } |
|
| 164 |
+ } |
|
| 165 |
+ |
|
| 166 |
+ return nil |
|
| 167 |
+ }) |
|
| 168 |
+ if err != nil {
|
|
| 169 |
+ return nil, err |
|
| 170 |
+ } |
|
| 171 |
+ err = filepath.Walk(oldDir, func(oldPath string, f os.FileInfo, err error) error {
|
|
| 172 |
+ if err != nil {
|
|
| 173 |
+ return err |
|
| 174 |
+ } |
|
| 175 |
+ |
|
| 176 |
+ // Rebase path |
|
| 177 |
+ relPath, err := filepath.Rel(oldDir, oldPath) |
|
| 178 |
+ if err != nil {
|
|
| 179 |
+ return err |
|
| 180 |
+ } |
|
| 181 |
+ relPath = filepath.Join("/", relPath)
|
|
| 182 |
+ |
|
| 183 |
+ // Skip root |
|
| 184 |
+ if relPath == "/" {
|
|
| 185 |
+ return nil |
|
| 186 |
+ } |
|
| 187 |
+ |
|
| 188 |
+ change := Change{
|
|
| 189 |
+ Path: relPath, |
|
| 190 |
+ } |
|
| 191 |
+ |
|
| 192 |
+ newPath := filepath.Join(newDir, relPath) |
|
| 193 |
+ |
|
| 194 |
+ var newStat = &syscall.Stat_t{}
|
|
| 195 |
+ err = syscall.Lstat(newPath, newStat) |
|
| 196 |
+ if err != nil && os.IsNotExist(err) {
|
|
| 197 |
+ change.Kind = ChangeDelete |
|
| 198 |
+ changes = append(changes, change) |
|
| 199 |
+ } |
|
| 200 |
+ |
|
| 201 |
+ return nil |
|
| 202 |
+ }) |
|
| 203 |
+ if err != nil {
|
|
| 204 |
+ return nil, err |
|
| 205 |
+ } |
|
| 206 |
+ return changes, nil |
|
| 207 |
+} |
| 0 | 208 |
deleted file mode 100644 |
| ... | ... |
@@ -1,208 +0,0 @@ |
| 1 |
-package docker |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "os" |
|
| 6 |
- "path/filepath" |
|
| 7 |
- "strings" |
|
| 8 |
- "syscall" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-type ChangeType int |
|
| 12 |
- |
|
| 13 |
-const ( |
|
| 14 |
- ChangeModify = iota |
|
| 15 |
- ChangeAdd |
|
| 16 |
- ChangeDelete |
|
| 17 |
-) |
|
| 18 |
- |
|
| 19 |
-type Change struct {
|
|
| 20 |
- Path string |
|
| 21 |
- Kind ChangeType |
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-func (change *Change) String() string {
|
|
| 25 |
- var kind string |
|
| 26 |
- switch change.Kind {
|
|
| 27 |
- case ChangeModify: |
|
| 28 |
- kind = "C" |
|
| 29 |
- case ChangeAdd: |
|
| 30 |
- kind = "A" |
|
| 31 |
- case ChangeDelete: |
|
| 32 |
- kind = "D" |
|
| 33 |
- } |
|
| 34 |
- return fmt.Sprintf("%s %s", kind, change.Path)
|
|
| 35 |
-} |
|
| 36 |
- |
|
| 37 |
-func Changes(layers []string, rw string) ([]Change, error) {
|
|
| 38 |
- var changes []Change |
|
| 39 |
- err := filepath.Walk(rw, func(path string, f os.FileInfo, err error) error {
|
|
| 40 |
- if err != nil {
|
|
| 41 |
- return err |
|
| 42 |
- } |
|
| 43 |
- |
|
| 44 |
- // Rebase path |
|
| 45 |
- path, err = filepath.Rel(rw, path) |
|
| 46 |
- if err != nil {
|
|
| 47 |
- return err |
|
| 48 |
- } |
|
| 49 |
- path = filepath.Join("/", path)
|
|
| 50 |
- |
|
| 51 |
- // Skip root |
|
| 52 |
- if path == "/" {
|
|
| 53 |
- return nil |
|
| 54 |
- } |
|
| 55 |
- |
|
| 56 |
- // Skip AUFS metadata |
|
| 57 |
- if matched, err := filepath.Match("/.wh..wh.*", path); err != nil || matched {
|
|
| 58 |
- return err |
|
| 59 |
- } |
|
| 60 |
- |
|
| 61 |
- change := Change{
|
|
| 62 |
- Path: path, |
|
| 63 |
- } |
|
| 64 |
- |
|
| 65 |
- // Find out what kind of modification happened |
|
| 66 |
- file := filepath.Base(path) |
|
| 67 |
- // If there is a whiteout, then the file was removed |
|
| 68 |
- if strings.HasPrefix(file, ".wh.") {
|
|
| 69 |
- originalFile := file[len(".wh."):]
|
|
| 70 |
- change.Path = filepath.Join(filepath.Dir(path), originalFile) |
|
| 71 |
- change.Kind = ChangeDelete |
|
| 72 |
- } else {
|
|
| 73 |
- // Otherwise, the file was added |
|
| 74 |
- change.Kind = ChangeAdd |
|
| 75 |
- |
|
| 76 |
- // ...Unless it already existed in a top layer, in which case, it's a modification |
|
| 77 |
- for _, layer := range layers {
|
|
| 78 |
- stat, err := os.Stat(filepath.Join(layer, path)) |
|
| 79 |
- if err != nil && !os.IsNotExist(err) {
|
|
| 80 |
- return err |
|
| 81 |
- } |
|
| 82 |
- if err == nil {
|
|
| 83 |
- // The file existed in the top layer, so that's a modification |
|
| 84 |
- |
|
| 85 |
- // However, if it's a directory, maybe it wasn't actually modified. |
|
| 86 |
- // If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar |
|
| 87 |
- if stat.IsDir() && f.IsDir() {
|
|
| 88 |
- if f.Size() == stat.Size() && f.Mode() == stat.Mode() && f.ModTime() == stat.ModTime() {
|
|
| 89 |
- // Both directories are the same, don't record the change |
|
| 90 |
- return nil |
|
| 91 |
- } |
|
| 92 |
- } |
|
| 93 |
- change.Kind = ChangeModify |
|
| 94 |
- break |
|
| 95 |
- } |
|
| 96 |
- } |
|
| 97 |
- } |
|
| 98 |
- |
|
| 99 |
- // Record change |
|
| 100 |
- changes = append(changes, change) |
|
| 101 |
- return nil |
|
| 102 |
- }) |
|
| 103 |
- if err != nil && !os.IsNotExist(err) {
|
|
| 104 |
- return nil, err |
|
| 105 |
- } |
|
| 106 |
- return changes, nil |
|
| 107 |
-} |
|
| 108 |
- |
|
| 109 |
-func ChangesDirs(newDir, oldDir string) ([]Change, error) {
|
|
| 110 |
- var changes []Change |
|
| 111 |
- err := filepath.Walk(newDir, func(newPath string, f os.FileInfo, err error) error {
|
|
| 112 |
- if err != nil {
|
|
| 113 |
- return err |
|
| 114 |
- } |
|
| 115 |
- |
|
| 116 |
- var newStat syscall.Stat_t |
|
| 117 |
- err = syscall.Lstat(newPath, &newStat) |
|
| 118 |
- if err != nil {
|
|
| 119 |
- return err |
|
| 120 |
- } |
|
| 121 |
- |
|
| 122 |
- // Rebase path |
|
| 123 |
- relPath, err := filepath.Rel(newDir, newPath) |
|
| 124 |
- if err != nil {
|
|
| 125 |
- return err |
|
| 126 |
- } |
|
| 127 |
- relPath = filepath.Join("/", relPath)
|
|
| 128 |
- |
|
| 129 |
- // Skip root |
|
| 130 |
- if relPath == "/" || relPath == "/.docker-id" {
|
|
| 131 |
- return nil |
|
| 132 |
- } |
|
| 133 |
- |
|
| 134 |
- change := Change{
|
|
| 135 |
- Path: relPath, |
|
| 136 |
- } |
|
| 137 |
- |
|
| 138 |
- oldPath := filepath.Join(oldDir, relPath) |
|
| 139 |
- |
|
| 140 |
- var oldStat = &syscall.Stat_t{}
|
|
| 141 |
- err = syscall.Lstat(oldPath, oldStat) |
|
| 142 |
- if err != nil {
|
|
| 143 |
- if !os.IsNotExist(err) {
|
|
| 144 |
- return err |
|
| 145 |
- } |
|
| 146 |
- oldStat = nil |
|
| 147 |
- } |
|
| 148 |
- |
|
| 149 |
- if oldStat == nil {
|
|
| 150 |
- change.Kind = ChangeAdd |
|
| 151 |
- changes = append(changes, change) |
|
| 152 |
- } else {
|
|
| 153 |
- if oldStat.Ino != newStat.Ino || |
|
| 154 |
- oldStat.Mode != newStat.Mode || |
|
| 155 |
- oldStat.Uid != newStat.Uid || |
|
| 156 |
- oldStat.Gid != newStat.Gid || |
|
| 157 |
- oldStat.Rdev != newStat.Rdev || |
|
| 158 |
- oldStat.Size != newStat.Size || |
|
| 159 |
- oldStat.Blocks != newStat.Blocks || |
|
| 160 |
- oldStat.Mtim != newStat.Mtim || |
|
| 161 |
- oldStat.Ctim != newStat.Ctim {
|
|
| 162 |
- change.Kind = ChangeModify |
|
| 163 |
- changes = append(changes, change) |
|
| 164 |
- } |
|
| 165 |
- } |
|
| 166 |
- |
|
| 167 |
- return nil |
|
| 168 |
- }) |
|
| 169 |
- if err != nil {
|
|
| 170 |
- return nil, err |
|
| 171 |
- } |
|
| 172 |
- err = filepath.Walk(oldDir, func(oldPath string, f os.FileInfo, err error) error {
|
|
| 173 |
- if err != nil {
|
|
| 174 |
- return err |
|
| 175 |
- } |
|
| 176 |
- |
|
| 177 |
- // Rebase path |
|
| 178 |
- relPath, err := filepath.Rel(oldDir, oldPath) |
|
| 179 |
- if err != nil {
|
|
| 180 |
- return err |
|
| 181 |
- } |
|
| 182 |
- relPath = filepath.Join("/", relPath)
|
|
| 183 |
- |
|
| 184 |
- // Skip root |
|
| 185 |
- if relPath == "/" {
|
|
| 186 |
- return nil |
|
| 187 |
- } |
|
| 188 |
- |
|
| 189 |
- change := Change{
|
|
| 190 |
- Path: relPath, |
|
| 191 |
- } |
|
| 192 |
- |
|
| 193 |
- newPath := filepath.Join(newDir, relPath) |
|
| 194 |
- |
|
| 195 |
- var newStat = &syscall.Stat_t{}
|
|
| 196 |
- err = syscall.Lstat(newPath, newStat) |
|
| 197 |
- if err != nil && os.IsNotExist(err) {
|
|
| 198 |
- change.Kind = ChangeDelete |
|
| 199 |
- changes = append(changes, change) |
|
| 200 |
- } |
|
| 201 |
- |
|
| 202 |
- return nil |
|
| 203 |
- }) |
|
| 204 |
- if err != nil {
|
|
| 205 |
- return nil, err |
|
| 206 |
- } |
|
| 207 |
- return changes, nil |
|
| 208 |
-} |
| ... | ... |
@@ -7,7 +7,6 @@ import ( |
| 7 | 7 |
"flag" |
| 8 | 8 |
"fmt" |
| 9 | 9 |
"github.com/dotcloud/docker/archive" |
| 10 |
- "github.com/dotcloud/docker/graphdriver" // FIXME: graphdriver.Change is a placeholder for archive.Change |
|
| 11 | 10 |
"github.com/dotcloud/docker/term" |
| 12 | 11 |
"github.com/dotcloud/docker/utils" |
| 13 | 12 |
"github.com/kr/pty" |
| ... | ... |
@@ -397,7 +396,7 @@ func (container *Container) Inject(file io.Reader, pth string) error {
|
| 397 | 397 |
} |
| 398 | 398 |
|
| 399 | 399 |
// Return error if path exists |
| 400 |
- if _, err := os.Stat(path.Join(container.rwPath(), pth)); err == nil {
|
|
| 400 |
+ if _, err := os.Stat(path.Join(container.RootfsPath(), pth)); err == nil {
|
|
| 401 | 401 |
// Since err is nil, the path could be stat'd and it exists |
| 402 | 402 |
return fmt.Errorf("%s exists", pth)
|
| 403 | 403 |
} else if !os.IsNotExist(err) {
|
| ... | ... |
@@ -1402,7 +1401,7 @@ func (container *Container) Mount() error {
|
| 1402 | 1402 |
return container.runtime.Mount(container) |
| 1403 | 1403 |
} |
| 1404 | 1404 |
|
| 1405 |
-func (container *Container) Changes() ([]graphdriver.Change, error) {
|
|
| 1405 |
+func (container *Container) Changes() ([]archive.Change, error) {
|
|
| 1406 | 1406 |
return container.runtime.Changes(container) |
| 1407 | 1407 |
} |
| 1408 | 1408 |
|
| ... | ... |
@@ -61,7 +61,7 @@ func (d *Driver) DiffSize(id string) (int64, error) {
|
| 61 | 61 |
return -1, fmt.Errorf("Not implemented")
|
| 62 | 62 |
} |
| 63 | 63 |
|
| 64 |
-func (d *Driver) Changes(id string) ([]graphdriver.Change, error) {
|
|
| 64 |
+func (d *Driver) Changes(id string) ([]archive.Change, error) {
|
|
| 65 | 65 |
return nil, fmt.Errorf("Not implemented")
|
| 66 | 66 |
} |
| 67 | 67 |
|
| ... | ... |
@@ -5,12 +5,8 @@ import ( |
| 5 | 5 |
"github.com/dotcloud/docker/archive" |
| 6 | 6 |
) |
| 7 | 7 |
|
| 8 |
-type InitFunc func(root string) (Driver, error) |
|
| 9 | 8 |
|
| 10 |
-// FIXME: this is a temporary placeholder for archive.Change |
|
| 11 |
-// (to be merged from master) |
|
| 12 |
-type Change interface {
|
|
| 13 |
-} |
|
| 9 |
+type InitFunc func(root string) (Driver, error) |
|
| 14 | 10 |
|
| 15 | 11 |
type Driver interface {
|
| 16 | 12 |
Create(id, parent string) error |
| ... | ... |
@@ -20,7 +16,7 @@ type Driver interface {
|
| 20 | 20 |
|
| 21 | 21 |
Diff(id string) (archive.Archive, error) |
| 22 | 22 |
DiffSize(id string) (bytes int64, err error) |
| 23 |
- Changes(id string) ([]Change, error) |
|
| 23 |
+ Changes(id string) ([]archive.Change, error) |
|
| 24 | 24 |
|
| 25 | 25 |
Cleanup() error |
| 26 | 26 |
} |
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"container/list" |
| 6 | 6 |
"database/sql" |
| 7 | 7 |
"fmt" |
| 8 |
+ "github.com/dotcloud/docker/archive" |
|
| 8 | 9 |
_ "github.com/dotcloud/docker/devmapper" |
| 9 | 10 |
"github.com/dotcloud/docker/gograph" |
| 10 | 11 |
"github.com/dotcloud/docker/graphdriver" |
| ... | ... |
@@ -728,7 +729,7 @@ func (runtime *Runtime) Unmount(container *Container) error {
|
| 728 | 728 |
return nil |
| 729 | 729 |
} |
| 730 | 730 |
|
| 731 |
-func (runtime *Runtime) Changes(container *Container) ([]graphdriver.Change, error) {
|
|
| 731 |
+func (runtime *Runtime) Changes(container *Container) ([]archive.Change, error) {
|
|
| 732 | 732 |
return runtime.driver.Changes(container.ID) |
| 733 | 733 |
} |
| 734 | 734 |
|
| ... | ... |
@@ -9,7 +9,6 @@ import ( |
| 9 | 9 |
"github.com/dotcloud/docker/auth" |
| 10 | 10 |
"github.com/dotcloud/docker/engine" |
| 11 | 11 |
"github.com/dotcloud/docker/gograph" |
| 12 |
- "github.com/dotcloud/docker/graphdriver" // FIXME: graphdriver.Change is a placeholder for archive.Change |
|
| 13 | 12 |
"github.com/dotcloud/docker/registry" |
| 14 | 13 |
"github.com/dotcloud/docker/utils" |
| 15 | 14 |
"io" |
| ... | ... |
@@ -449,7 +448,7 @@ func (srv *Server) ContainerTop(name, ps_args string) (*APITop, error) {
|
| 449 | 449 |
return nil, fmt.Errorf("No such container: %s", name)
|
| 450 | 450 |
} |
| 451 | 451 |
|
| 452 |
-func (srv *Server) ContainerChanges(name string) ([]graphdriver.Change, error) {
|
|
| 452 |
+func (srv *Server) ContainerChanges(name string) ([]archive.Change, error) {
|
|
| 453 | 453 |
if container := srv.runtime.Get(name); container != nil {
|
| 454 | 454 |
return container.Changes() |
| 455 | 455 |
} |
| ... | ... |
@@ -23,6 +23,7 @@ btrfs_reflink(int fd_out, int fd_in) |
| 23 | 23 |
import "C" |
| 24 | 24 |
import ( |
| 25 | 25 |
"fmt" |
| 26 |
+ "github.com/dotcloud/docker/archive" |
|
| 26 | 27 |
"github.com/dotcloud/docker/namesgenerator" |
| 27 | 28 |
"github.com/dotcloud/docker/utils" |
| 28 | 29 |
"io" |
| ... | ... |
@@ -33,6 +34,12 @@ import ( |
| 33 | 33 |
"syscall" |
| 34 | 34 |
) |
| 35 | 35 |
|
| 36 |
+ |
|
| 37 |
+type Change struct {
|
|
| 38 |
+ archive.Change |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+ |
|
| 36 | 42 |
// Compare two Config struct. Do not compare the "Image" nor "Hostname" fields |
| 37 | 43 |
// If OpenStdin is set, then it differs |
| 38 | 44 |
func CompareConfig(a, b *Config) bool {
|