FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pretend-git/abspath.c at master · submitgit/pretend-git · GitHub
submitgit
/
pretend-git
Public
forked from
git/git
Notifications
You must be signed in to change notification settings
Fork
2
Star
0
Code
Pull requests
3
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
pretend-git
/
abspath.c
Copy path
More file actions
More file actions
Latest commit
History
History
History
183 lines (164 loc) · 4.4 KB
Breadcrumbs
pretend-git
/
abspath.c
Copy path
File metadata and controls
183 lines (164 loc) · 4.4 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include
"cache.h"
/*
* Do not use this for inspecting *tracked* content. When path is a
* symlink to a directory, we do not want to say it is a directory when
* dealing with tracked content in the working tree.
*/
int
is_directory
(
const
char
*
path
)
{
struct
stat
st
;
return
(!
stat
(
path
,
&
st
)
&&
S_ISDIR
(
st
.
st_mode
));
}
/* We allow "recursive" symbolic links. Only within reason, though. */
#define
MAXDEPTH
5
/*
* Return the real path (i.e., absolute path, with symlinks resolved
* and extra slashes removed) equivalent to the specified path. (If
* you want an absolute path but don't mind links, use
* absolute_path().) The return value is a pointer to a static
* buffer.
*
* The input and all intermediate paths must be shorter than MAX_PATH.
* The directory part of path (i.e., everything up to the last
* dir_sep) must denote a valid, existing directory, but the last
* component need not exist. If die_on_error is set, then die with an
* informative error message if there is a problem. Otherwise, return
* NULL on errors (without generating any output).
*
* If path is our buffer, then return path, as it's already what the
* user wants.
*/
static
const
char
*
real_path_internal
(
const
char
*
path
,
int
die_on_error
)
{
static
struct
strbuf
sb
=
STRBUF_INIT
;
char
*
retval
=
NULL
;
/*
* If we have to temporarily chdir(), store the original CWD
* here so that we can chdir() back to it at the end of the
* function:
*/
struct
strbuf
cwd
=
STRBUF_INIT
;
int
depth
=
MAXDEPTH
;
char
*
last_elem
=
NULL
;
struct
stat
st
;
/* We've already done it */
if
(
path
==
sb
.
buf
)
return
path
;
if
(!
*
path
) {
if
(
die_on_error
)
die
(
"The empty string is not a valid path"
);
else
goto
error_out
;
}
strbuf_reset
(
&
sb
);
strbuf_addstr
(
&
sb
,
path
);
while
(
depth
--
) {
if
(!
is_directory
(
sb
.
buf
)) {
char
*
last_slash
=
find_last_dir_sep
(
sb
.
buf
);
if
(
last_slash
) {
last_elem
=
xstrdup
(
last_slash
+
1
);
strbuf_setlen
(
&
sb
,
last_slash
-
sb
.
buf
+
1
);
}
else
{
last_elem
=
xmemdupz
(
sb
.
buf
,
sb
.
len
);
strbuf_reset
(
&
sb
);
}
}
if
(
sb
.
len
) {
if
(!
cwd
.
len
&&
strbuf_getcwd
(
&
cwd
)) {
if
(
die_on_error
)
die_errno
(
"Could not get current working directory"
);
else
goto
error_out
;
}
if
(
chdir
(
sb
.
buf
)) {
if
(
die_on_error
)
die_errno
(
"Could not switch to '%s'"
,
sb
.
buf
);
else
goto
error_out
;
}
}
if
(
strbuf_getcwd
(
&
sb
)) {
if
(
die_on_error
)
die_errno
(
"Could not get current working directory"
);
else
goto
error_out
;
}
if
(
last_elem
) {
if
(
sb
.
len
&&
!
is_dir_sep
(
sb
.
buf
[
sb
.
len
-
1
]))
strbuf_addch
(
&
sb
,
'/'
);
strbuf_addstr
(
&
sb
,
last_elem
);
free
(
last_elem
);
last_elem
=
NULL
;
}
if
(!
lstat
(
sb
.
buf
,
&
st
)
&&
S_ISLNK
(
st
.
st_mode
)) {
struct
strbuf
next_sb
=
STRBUF_INIT
;
ssize_t
len
=
strbuf_readlink
(
&
next_sb
,
sb
.
buf
,
0
);
if
(
len
<
0
) {
if
(
die_on_error
)
die_errno
(
"Invalid symlink '%s'"
,
sb
.
buf
);
else
goto
error_out
;
}
strbuf_swap
(
&
sb
,
&
next_sb
);
strbuf_release
(
&
next_sb
);
}
else
break
;
}
retval
=
sb
.
buf
;
error_out
:
free
(
last_elem
);
if
(
cwd
.
len
&&
chdir
(
cwd
.
buf
))
die_errno
(
"Could not change back to '%s'"
,
cwd
.
buf
);
strbuf_release
(
&
cwd
);
return
retval
;
}
const
char
*
real_path
(
const
char
*
path
)
{
return
real_path_internal
(
path
,
1
);
}
const
char
*
real_path_if_valid
(
const
char
*
path
)
{
return
real_path_internal
(
path
,
0
);
}
/*
* Use this to get an absolute path from a relative one. If you want
* to resolve links, you should use real_path.
*/
const
char
*
absolute_path
(
const
char
*
path
)
{
static
struct
strbuf
sb
=
STRBUF_INIT
;
strbuf_reset
(
&
sb
);
strbuf_add_absolute_path
(
&
sb
,
path
);
return
sb
.
buf
;
}
/*
* Unlike prefix_path, this should be used if the named file does
* not have to interact with index entry; i.e. name of a random file
* on the filesystem.
*/
const
char
*
prefix_filename
(
const
char
*
pfx
,
int
pfx_len
,
const
char
*
arg
)
{
static
struct
strbuf
path
=
STRBUF_INIT
;
#ifndef
GIT_WINDOWS_NATIVE
if
(!
pfx_len
||
is_absolute_path
(
arg
))
return
arg
;
strbuf_reset
(
&
path
);
strbuf_add
(
&
path
,
pfx
,
pfx_len
);
strbuf_addstr
(
&
path
,
arg
);
#else
char
*
p
;
/* don't add prefix to absolute paths, but still replace '\' by '/' */
strbuf_reset
(
&
path
);
if
(
is_absolute_path
(
arg
))
pfx_len
=
0
;
else
if
(
pfx_len
)
strbuf_add
(
&
path
,
pfx
,
pfx_len
);
strbuf_addstr
(
&
path
,
arg
);
for
(
p
=
path
.
buf
+
pfx_len
;
*
p
;
p
++
)
if
(
*
p
==
'\\'
)
*
p
=
'/'
;
#endif
return
path
.
buf
;
}
Back
|
FazBrowse Home
|
New Git URL