-
Notifications
You must be signed in to change notification settings - Fork 0
/
status_common_prefix.go
71 lines (55 loc) · 1.65 KB
/
status_common_prefix.go
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
package cmd
import "path"
/*
commonPrefix returns common most significant part of a 'path'
'sep' path separator
'paths' slice where commonality must be found
*/
func commonPrefix(sep byte, paths []string) string {
/* Handle special cases */
switch len(paths) {
case 0:
return ""
case 1:
return path.Clean(paths[0])
}
/* Note, we treat string as []byte, not []rune as is often
done in Go. (And sep as byte, not rune). This is because
most/all supported OS' treat paths as string of non-zero
bytes. A filename may be displayed as a sequence of Unicode
runes (typically encoded as UTF-8) but paths are
not required to be valid UTF-8 or in any normalized form
(e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
file names */
c := []byte(path.Clean(paths[0]))
/* We add a trailing sep to handle the case where the
common prefix directory is included in the path list
(e.g. /home/user1, /home/user1/foo, /home/user1/bar).
path.Clean will have cleaned off trailing / separators with
the exception of the root directory, "/" (in which case we
make it "//", but this will get fixed up to "/" bellow) */
c = append(c, sep)
/* Ignore the first path since it's already in c */
for _, v := range paths[1:] {
/* Clean up each path before testing it */
v = path.Clean(v) + string(sep)
/* Find the first non-common byte and truncate c */
if len(v) < len(c) {
c = c[:len(v)]
}
for i := 0; i < len(c); i++ {
if v[i] != c[i] {
c = c[:i]
break
}
}
}
/* Remove trailing non-separator characters and the final separator */
for i := len(c) - 1; i >= 0; i-- {
if c[i] == sep {
c = c[:i]
break
}
}
return string(c)
}