-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibpath
147 lines (122 loc) · 3.5 KB
/
libpath
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env bash
. bpm
bpm::include assign
bpm::include log
# Resolves a directory. If you are given a relative path, this turns it into
# an absolute path.
#
# $1 - Destination variable name.
# $2 - Path to resolve.
# $3 - Path to resolve against (defaults to current directory).
#
# Returns true (0) when everything works. Returns false (1) when the directory
# does not exist (thus it can't be resolved). Returns false (2) when the
# path to resolve against does not exist.
path::absoluteDir() {
local oldDir result
oldDir=$PWD
if [[ -n "${3-}" ]]; then
cd "$3" 2> /dev/null || return 2
fi
cd "$2" 2> /dev/null || return 1
result=$PWD
cd "$oldDir"
local "${1-}" && assign::value "$1" "$result"
}
# Resolves a file. If you are given a relative path, this turns it into
# an absolute path.
#
# $1 - Destination variable name.
# $2 - File path to resolve.
# $3 - Path to resolve against (defaults to current directory).
#
# Returns true (0) when everything works. Returns error codes from
# path::absoluteDir when there are problems.
path::absoluteFile() {
local fileDir result
path::dirname fileDir "$2"
path::absoluteDir result "$fileDir" ${3+"$3"} || return $?
result=${result%/}
local "${1-}" && assign::value "$1" "$result/${2##*/}"
}
# Equivalent to calling `dirname` but does not make a subshell, so this is
# roughly twice as fast.
#
# $1 - Destination variable name. This is set to the parent folder.
# $2 - Filename or directory name.
#
# Examples
#
# path::dirname dest a/file/somewhere
# echo "$dest" # "a/file"
#
# path::dirname dest ./filename
# echo "$dest" # "."
#
# path::dirname dest filename
# echo "$dest" # "."
#
# path::dirname dest some/dir/
# echo "$dest" # "some"
#
# path::dirname dest dir/
# echo "$dest" # "."
#
# Returns nothing.
path::dirname() {
local d p
p=$2
if [[ "${#p}" -gt 1 ]]; then
p=${p%/}
fi
if [[ "$p" == */* ]]; then
d=${p%/*}
local "${1-}" && assign::value "$1" "${d:-/}"
return
fi
local "${1-}" && assign::value "$1" "."
}
# Performs a single test for a target in the current directory or any parent.
# When found, supplies the folder name to the destination variable name. The
# location will be root-relative.
#
# $1 - Destination variable name.
# $2 - The type of test to perform.
# $3 - The target that you are testing.
#
# Examples:
#
# # Search for a bpm.ini file in the current folder or any parent.
# if ! path::findParentContaining result -f bpm.ini; then
# echo "Sorry, did not find the file" >&2
# else
# echo "Folder containing file: $result"
# echo "Full path: $result/bpm.ini"
# fi
#
# # Search for a particular library
# path::findParentContaining -d bpm_modules/is
#
# Returning success and an empty string is a valid response, so make sure you
# use the return code from the function.
#
# Returns true (0) if the target was found.
path::findParentContaining() {
local dir
dir=$PWD
# Scan parent folders for `bpm.ini`.
while true; do
# Nasty use of eval, but necessary. Alternatives are welcome.
if eval [[ "$2" "$dir/$3" ]]; then
log::debug "Found target $2: $dir/$3"
local "${1-}" && assign::value "$1" "$dir/$3"
return 0
fi
if [[ -z "$dir" ]]; then
log::debug "Did not find target $2: $3"
return 1
fi
log::debug "Target $2 not found in folder: $dir"
dir=${dir%/*}
done
}