Signed-off-by: Cristian Staretu <cristian.staretu@gmail.com>
| ... | ... |
@@ -11,7 +11,7 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/pkg/system" |
| 12 | 12 |
) |
| 13 | 13 |
|
| 14 |
-// canonicalTarNameForPath returns platform-specific filepath |
|
| 14 |
+// CanonicalTarNameForPath returns platform-specific filepath |
|
| 15 | 15 |
// to canonical posix-style path for tar archival. p is relative |
| 16 | 16 |
// path. |
| 17 | 17 |
func CanonicalTarNameForPath(p string) (string, error) {
|
| ... | ... |
@@ -133,7 +133,7 @@ func testBreakout(untarFn string, tmpdir string, headers []*tar.Header) error {
|
| 133 | 133 |
helloStat.Size() != fi.Size() || |
| 134 | 134 |
!bytes.Equal(helloData, b) {
|
| 135 | 135 |
// codepath taken if hello has been modified |
| 136 |
- return fmt.Errorf("archive breakout: file %q has been modified. Contents: expected=%q, got=%q. FileInfo: expected=%#v, got=%#v.", hello, helloData, b, helloStat, fi)
|
|
| 136 |
+ return fmt.Errorf("archive breakout: file %q has been modified. Contents: expected=%q, got=%q. FileInfo: expected=%#v, got=%#v", hello, helloData, b, helloStat, fi)
|
|
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 | 139 |
// Check that nothing in dest/ has the same content as victim/hello. |
| ... | ... |
@@ -58,6 +58,10 @@ func untar() {
|
| 58 | 58 |
os.Exit(0) |
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 |
+// Untar reads a stream of bytes from `archive`, parses it as a tar archive, |
|
| 62 |
+// and unpacks it into the directory at `dest`. |
|
| 63 |
+// The archive may be compressed with one of the following algorithms: |
|
| 64 |
+// identity (uncompressed), gzip, bzip2, xz. |
|
| 61 | 65 |
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
|
| 62 | 66 |
if tarArchive == nil {
|
| 63 | 67 |
return fmt.Errorf("Empty archive")
|
| ... | ... |
@@ -133,17 +137,18 @@ func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error |
| 133 | 133 |
return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output)
|
| 134 | 134 |
} |
| 135 | 135 |
return nil |
| 136 |
- } else {
|
|
| 137 |
- cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))
|
|
| 138 |
- out, err := cmd.CombinedOutput() |
|
| 139 |
- if err != nil {
|
|
| 140 |
- return fmt.Errorf("Untar %s %s", err, out)
|
|
| 141 |
- } |
|
| 142 |
- return nil |
|
| 143 | 136 |
} |
| 137 |
+ cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))
|
|
| 138 |
+ out, err := cmd.CombinedOutput() |
|
| 139 |
+ if err != nil {
|
|
| 140 |
+ return fmt.Errorf("Untar %s %s", err, out)
|
|
| 141 |
+ } |
|
| 142 |
+ return nil |
|
| 144 | 143 |
|
| 145 | 144 |
} |
| 146 | 145 |
|
| 146 |
+// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other. |
|
| 147 |
+// If either Tar or Untar fails, TarUntar aborts and returns the error. |
|
| 147 | 148 |
func TarUntar(src, dst string) error {
|
| 148 | 149 |
return chrootArchiver.TarUntar(src, dst) |
| 149 | 150 |
} |
| ... | ... |
@@ -69,6 +69,9 @@ func applyLayer() {
|
| 69 | 69 |
os.Exit(0) |
| 70 | 70 |
} |
| 71 | 71 |
|
| 72 |
+// ApplyLayer parses a diff in the standard layer format from `layer`, and |
|
| 73 |
+// applies it to the directory `dest`. Returns the size in bytes of the |
|
| 74 |
+// contents of the layer. |
|
| 72 | 75 |
func ApplyLayer(dest string, layer archive.ArchiveReader) (size int64, err error) {
|
| 73 | 76 |
dest = filepath.Clean(dest) |
| 74 | 77 |
decompressed, err := archive.DecompressStream(layer) |
| ... | ... |
@@ -20,7 +20,7 @@ func Empty(pattern string) bool {
|
| 20 | 20 |
return pattern == "" |
| 21 | 21 |
} |
| 22 | 22 |
|
| 23 |
-// Cleanpatterns takes a slice of patterns returns a new |
|
| 23 |
+// CleanPatterns takes a slice of patterns returns a new |
|
| 24 | 24 |
// slice of patterns cleaned with filepath.Clean, stripped |
| 25 | 25 |
// of any empty patterns and lets the caller know whether the |
| 26 | 26 |
// slice contains any exception patterns (prefixed with !). |
| ... | ... |
@@ -73,7 +73,7 @@ func Matches(file string, patterns []string) (bool, error) {
|
| 73 | 73 |
return OptimizedMatches(file, patterns, patDirs) |
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 |
-// Matches is basically the same as fileutils.Matches() but optimized for archive.go. |
|
| 76 |
+// OptimizedMatches is basically the same as fileutils.Matches() but optimized for archive.go. |
|
| 77 | 77 |
// It will assume that the inputs have been preprocessed and therefore the function |
| 78 | 78 |
// doen't need to do as much error checking and clean-up. This was done to avoid |
| 79 | 79 |
// repeating these steps on each file being checked during the archive process. |
| ... | ... |
@@ -8,6 +8,8 @@ import ( |
| 8 | 8 |
_ "code.google.com/p/gosqlite/sqlite3" // registers sqlite |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 |
+// NewSqliteConn opens a connection to a sqlite |
|
| 12 |
+// database. |
|
| 11 | 13 |
func NewSqliteConn(root string) (*Database, error) {
|
| 12 | 14 |
conn, err := sql.Open("sqlite3", root)
|
| 13 | 15 |
if err != nil {
|
| ... | ... |
@@ -41,17 +41,25 @@ type Edge struct {
|
| 41 | 41 |
ParentID string |
| 42 | 42 |
} |
| 43 | 43 |
|
| 44 |
+// Entities stores the list of entities |
|
| 44 | 45 |
type Entities map[string]*Entity |
| 46 |
+ |
|
| 47 |
+// Edges stores the relationships between entities |
|
| 45 | 48 |
type Edges []*Edge |
| 46 | 49 |
|
| 50 |
+// WalkFunc is a function invoked to process an individual entity |
|
| 47 | 51 |
type WalkFunc func(fullPath string, entity *Entity) error |
| 48 | 52 |
|
| 49 |
-// Graph database for storing entities and their relationships |
|
| 53 |
+// Database is a graph database for storing entities and their relationships |
|
| 50 | 54 |
type Database struct {
|
| 51 | 55 |
conn *sql.DB |
| 52 | 56 |
mux sync.RWMutex |
| 53 | 57 |
} |
| 54 | 58 |
|
| 59 |
+// IsNonUniqueNameError processes the error to check if it's caused by |
|
| 60 |
+// a constraint violation. |
|
| 61 |
+// This is necessary because the error isn't the same across various |
|
| 62 |
+// sqlite versions. |
|
| 55 | 63 |
func IsNonUniqueNameError(err error) bool {
|
| 56 | 64 |
str := err.Error() |
| 57 | 65 |
// sqlite 3.7.17-1ubuntu1 returns: |
| ... | ... |
@@ -72,7 +80,7 @@ func IsNonUniqueNameError(err error) bool {
|
| 72 | 72 |
return false |
| 73 | 73 |
} |
| 74 | 74 |
|
| 75 |
-// Create a new graph database initialized with a root entity |
|
| 75 |
+// NewDatabase creates a new graph database initialized with a root entity |
|
| 76 | 76 |
func NewDatabase(conn *sql.DB) (*Database, error) {
|
| 77 | 77 |
if conn == nil {
|
| 78 | 78 |
return nil, fmt.Errorf("Database connection cannot be nil")
|
| ... | ... |
@@ -163,7 +171,7 @@ func (db *Database) Set(fullPath, id string) (*Entity, error) {
|
| 163 | 163 |
return e, nil |
| 164 | 164 |
} |
| 165 | 165 |
|
| 166 |
-// Return true if a name already exists in the database |
|
| 166 |
+// Exists returns true if a name already exists in the database |
|
| 167 | 167 |
func (db *Database) Exists(name string) bool {
|
| 168 | 168 |
db.mux.RLock() |
| 169 | 169 |
defer db.mux.RUnlock() |
| ... | ... |
@@ -190,14 +198,14 @@ func (db *Database) setEdge(parentPath, name string, e *Entity, tx *sql.Tx) erro |
| 190 | 190 |
return nil |
| 191 | 191 |
} |
| 192 | 192 |
|
| 193 |
-// Return the root "/" entity for the database |
|
| 193 |
+// RootEntity returns the root "/" entity for the database |
|
| 194 | 194 |
func (db *Database) RootEntity() *Entity {
|
| 195 | 195 |
return &Entity{
|
| 196 | 196 |
id: "0", |
| 197 | 197 |
} |
| 198 | 198 |
} |
| 199 | 199 |
|
| 200 |
-// Return the entity for a given path |
|
| 200 |
+// Get returns the entity for a given path |
|
| 201 | 201 |
func (db *Database) Get(name string) *Entity {
|
| 202 | 202 |
db.mux.RLock() |
| 203 | 203 |
defer db.mux.RUnlock() |
| ... | ... |
@@ -274,7 +282,7 @@ func (db *Database) Walk(name string, walkFunc WalkFunc, depth int) error {
|
| 274 | 274 |
return nil |
| 275 | 275 |
} |
| 276 | 276 |
|
| 277 |
-// Return the children of the specified entity |
|
| 277 |
+// Children returns the children of the specified entity |
|
| 278 | 278 |
func (db *Database) Children(name string, depth int) ([]WalkMeta, error) {
|
| 279 | 279 |
db.mux.RLock() |
| 280 | 280 |
defer db.mux.RUnlock() |
| ... | ... |
@@ -287,7 +295,7 @@ func (db *Database) Children(name string, depth int) ([]WalkMeta, error) {
|
| 287 | 287 |
return db.children(e, name, depth, nil) |
| 288 | 288 |
} |
| 289 | 289 |
|
| 290 |
-// Return the parents of a specified entity |
|
| 290 |
+// Parents returns the parents of a specified entity |
|
| 291 | 291 |
func (db *Database) Parents(name string) ([]string, error) {
|
| 292 | 292 |
db.mux.RLock() |
| 293 | 293 |
defer db.mux.RUnlock() |
| ... | ... |
@@ -299,7 +307,7 @@ func (db *Database) Parents(name string) ([]string, error) {
|
| 299 | 299 |
return db.parents(e) |
| 300 | 300 |
} |
| 301 | 301 |
|
| 302 |
-// Return the refrence count for a specified id |
|
| 302 |
+// Refs returns the refrence count for a specified id |
|
| 303 | 303 |
func (db *Database) Refs(id string) int {
|
| 304 | 304 |
db.mux.RLock() |
| 305 | 305 |
defer db.mux.RUnlock() |
| ... | ... |
@@ -311,7 +319,7 @@ func (db *Database) Refs(id string) int {
|
| 311 | 311 |
return count |
| 312 | 312 |
} |
| 313 | 313 |
|
| 314 |
-// Return all the id's path references |
|
| 314 |
+// RefPaths returns all the id's path references |
|
| 315 | 315 |
func (db *Database) RefPaths(id string) Edges {
|
| 316 | 316 |
db.mux.RLock() |
| 317 | 317 |
defer db.mux.RUnlock() |
| ... | ... |
@@ -360,7 +368,7 @@ func (db *Database) Delete(name string) error {
|
| 360 | 360 |
return nil |
| 361 | 361 |
} |
| 362 | 362 |
|
| 363 |
-// Remove the entity with the specified id |
|
| 363 |
+// Purge removes the entity with the specified id |
|
| 364 | 364 |
// Walk the graph to make sure all references to the entity |
| 365 | 365 |
// are removed and return the number of references removed |
| 366 | 366 |
func (db *Database) Purge(id string) (int, error) {
|
| ... | ... |
@@ -480,7 +488,7 @@ func (db *Database) children(e *Entity, name string, depth int, entities []WalkM |
| 480 | 480 |
if depth != 0 {
|
| 481 | 481 |
nDepth := depth |
| 482 | 482 |
if depth != -1 {
|
| 483 |
- nDepth -= 1 |
|
| 483 |
+ nDepth-- |
|
| 484 | 484 |
} |
| 485 | 485 |
entities, err = db.children(child, meta.FullPath, nDepth, entities) |
| 486 | 486 |
if err != nil {
|
| ... | ... |
@@ -523,12 +531,12 @@ func (db *Database) child(parent *Entity, name string) *Entity {
|
| 523 | 523 |
return &Entity{id}
|
| 524 | 524 |
} |
| 525 | 525 |
|
| 526 |
-// Return the id used to reference this entity |
|
| 526 |
+// ID returns the id used to reference this entity |
|
| 527 | 527 |
func (e *Entity) ID() string {
|
| 528 | 528 |
return e.id |
| 529 | 529 |
} |
| 530 | 530 |
|
| 531 |
-// Return the paths sorted by depth |
|
| 531 |
+// Paths returns the paths sorted by depth |
|
| 532 | 532 |
func (e Entities) Paths() []string {
|
| 533 | 533 |
out := make([]string, len(e)) |
| 534 | 534 |
var i int |
| ... | ... |
@@ -10,7 +10,7 @@ func split(p string) []string {
|
| 10 | 10 |
return strings.Split(p, "/") |
| 11 | 11 |
} |
| 12 | 12 |
|
| 13 |
-// Returns the depth or number of / in a given path |
|
| 13 |
+// PathDepth returns the depth or number of / in a given path |
|
| 14 | 14 |
func PathDepth(p string) int {
|
| 15 | 15 |
parts := split(p) |
| 16 | 16 |
if len(parts) == 2 && parts[1] == "" {
|
| ... | ... |
@@ -7,7 +7,7 @@ import ( |
| 7 | 7 |
"github.com/docker/docker/pkg/jsonmessage" |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 |
-// Request a given URL and return an io.Reader |
|
| 10 |
+// Download requests a given URL and returns an io.Reader |
|
| 11 | 11 |
func Download(url string) (resp *http.Response, err error) {
|
| 12 | 12 |
if resp, err = http.Get(url); err != nil {
|
| 13 | 13 |
return nil, err |
| ... | ... |
@@ -18,6 +18,7 @@ func Download(url string) (resp *http.Response, err error) {
|
| 18 | 18 |
return resp, nil |
| 19 | 19 |
} |
| 20 | 20 |
|
| 21 |
+// NewHTTPRequestError returns a JSON response error |
|
| 21 | 22 |
func NewHTTPRequestError(msg string, res *http.Response) error {
|
| 22 | 23 |
return &jsonmessage.JSONError{
|
| 23 | 24 |
Message: msg, |
| ... | ... |
@@ -26,6 +26,8 @@ func ResumableRequestReader(c *http.Client, r *http.Request, maxfail uint32, tot |
| 26 | 26 |
return &resumableRequestReader{client: c, request: r, maxFailures: maxfail, totalSize: totalsize}
|
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 |
+// ResumableRequestReaderWithInitialResponse makes it possible to resume |
|
| 30 |
+// reading the body of an already initiated request. |
|
| 29 | 31 |
func ResumableRequestReaderWithInitialResponse(c *http.Client, r *http.Request, maxfail uint32, totalsize int64, initialResponse *http.Response) io.ReadCloser {
|
| 30 | 32 |
return &resumableRequestReader{client: c, request: r, maxFailures: maxfail, totalSize: totalsize, currentResponse: initialResponse}
|
| 31 | 33 |
} |
| ... | ... |
@@ -1,5 +1,5 @@ |
| 1 | 1 |
/* |
| 2 |
-listenbuffer uses the kernel's listening backlog functionality to queue |
|
| 2 |
+Package listenbuffer uses the kernel's listening backlog functionality to queue |
|
| 3 | 3 |
connections, allowing applications to start listening immediately and handle |
| 4 | 4 |
connections later. This is signaled by closing the activation channel passed to |
| 5 | 5 |
the constructor. |