~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
79
80
81
package formula

import (
	"os"
	"path/filepath"
)

// This function and its tests are being submitted upstream through:
//
//     http://codereview.appspot.com/4981049
//
// Meanwhile, we'll inline them here.

// Rel returns a relative path that is equivalent to targpath when
// joined to basepath with an intervening separator. That is,
// Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself.
// An error is returned if targpath can't be made relative to basepath or if
// knowing the current working directory would be necessary to compute it.
func filepath_Rel(basepath, targpath string) (string, os.Error) {
	baseVol := filepath.VolumeName(basepath)
	targVol := filepath.VolumeName(targpath)
	base := filepath.Clean(basepath)
	targ := filepath.Clean(targpath)
	if targ == base {
		return ".", nil
	}
	base = base[len(baseVol):]
	targ = targ[len(targVol):]
	if base == "." {
		base = ""
	}
	// Can't use IsAbs - `\a` and `a` are both relative in Windows.
	baseSlashed := len(base) > 0 && base[0] == filepath.Separator
	targSlashed := len(targ) > 0 && targ[0] == filepath.Separator
	if baseSlashed != targSlashed || baseVol != targVol {
		return "", os.NewError("Rel: can't make " + targ + " relative to " + base)
	}
	// Position base[b0:bi] and targ[t0:ti] at the first differing elements.
	bl := len(base)
	tl := len(targ)
	var b0, bi, t0, ti int
	for {
		for bi < bl && base[bi] != filepath.Separator {
			bi++
		}
		for ti < tl && targ[ti] != filepath.Separator {
			ti++
		}
		if targ[t0:ti] != base[b0:bi] {
			break
		}
		if bi < bl {
			bi++
		}
		if ti < tl {
			ti++
		}
		b0 = bi
		t0 = ti
	}
	if base[b0:bi] == ".." {
		return "", os.NewError("Rel: can't make " + targ + " relative to " + base)
	}
	if b0 != bl {
		// Base elements left. Must go up before going down.
		buf := []byte("..")
		for i := b0; i < bl; i++ {
			if base[i] == filepath.Separator {
				buf = append(buf, '/', '.', '.')
			}
		}
		if t0 != tl {
			buf = append(buf, '/')
			buf = append(buf, []byte(targ[t0:])...)
		}
		return string(buf), nil
	}
	return targ[t0:], nil
}