~rogpeppe/juju-core/438-local-instance-Addresses

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package charm

import (
	"os"
	"path/filepath"
	"sort"
)

// Drop in replacement for filepath.Walk while issue 2237 is not solved:
//
//    http://code.google.com/p/go/issues/detail?id=2237

type walkErrorHandler interface {
	Error(path string, err os.Error)
}

// walk walks the file tree rooted at root, calling v.VisitDir or
// v.VisitFile for each directory or file in the tree, including root.
// If v.VisitDir returns false, Walk skips the directory's entries;
// otherwise it invokes itself for each directory entry in sorted order.
// If the visitor implements the walkErrorHandler interface, any errors
// found will be dispatched to it.
func walk(root string, v filepath.Visitor) {
	f, err := os.Lstat(root)
	if err != nil {
		if eh, ok := v.(walkErrorHandler); ok {
			eh.Error(root, err)
		}
		return // can't progress
	}
	walk_(root, f, v)
}

func walk_(path string, f *os.FileInfo, v filepath.Visitor) {
	if !f.IsDirectory() {
		v.VisitFile(path, f)
		return
	}
	if !v.VisitDir(path, f) {
		return // skip directory entries
	}
	list, err := readDir(path)
	if err != nil {
		if eh, ok := v.(walkErrorHandler); ok {
			eh.Error(path, err)
		}
	}
	for _, e := range list {
		walk_(filepath.Join(path, e.Name), e, v)
	}
}

func readDir(dirname string) ([]*os.FileInfo, os.Error) {
	f, err := os.Open(dirname)
	if err != nil {
		return nil, err
	}
	list, err := f.Readdir(-1)
	f.Close()
	if err != nil {
		return nil, err
	}
	fi := make(fileInfoList, len(list))
	for i := range list {
		fi[i] = &list[i]
	}
	sort.Sort(fi)
	return fi, nil
}

type fileInfoList []*os.FileInfo

func (f fileInfoList) Len() int           { return len(f) }
func (f fileInfoList) Less(i, j int) bool { return f[i].Name < f[j].Name }
func (f fileInfoList) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }