Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
48bcf81d
Commit
48bcf81d
authored
Jul 12, 2012
by
Vicent Martí
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #812 from arrbee/assorted-tweaks
Assorted goodies
parents
111ee3fe
54e29b93
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
512 additions
and
32 deletions
+512
-32
include/git2/config.h
+19
-1
include/git2/repository.h
+4
-1
src/buffer.c
+36
-0
src/buffer.h
+19
-0
src/config.c
+13
-3
src/config_file.c
+30
-7
src/config_file.h
+16
-1
src/path.c
+66
-3
src/path.h
+23
-0
src/repository.c
+83
-9
src/util.h
+1
-1
tests-clar/config/read.c
+75
-0
tests-clar/core/buffer.c
+47
-0
tests-clar/core/path.c
+51
-0
tests-clar/repo/setters.c
+27
-4
tests-clar/status/worktree.c
+2
-2
No files found.
include/git2/config.h
View file @
48bcf81d
...
@@ -33,7 +33,7 @@ struct git_config_file {
...
@@ -33,7 +33,7 @@ struct git_config_file {
int
(
*
set
)(
struct
git_config_file
*
,
const
char
*
key
,
const
char
*
value
);
int
(
*
set
)(
struct
git_config_file
*
,
const
char
*
key
,
const
char
*
value
);
int
(
*
set_multivar
)(
git_config_file
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
);
int
(
*
set_multivar
)(
git_config_file
*
cfg
,
const
char
*
name
,
const
char
*
regexp
,
const
char
*
value
);
int
(
*
del
)(
struct
git_config_file
*
,
const
char
*
key
);
int
(
*
del
)(
struct
git_config_file
*
,
const
char
*
key
);
int
(
*
foreach
)(
struct
git_config_file
*
,
int
(
*
fn
)(
const
char
*
,
const
char
*
,
void
*
),
void
*
data
);
int
(
*
foreach
)(
struct
git_config_file
*
,
const
char
*
,
int
(
*
fn
)(
const
char
*
,
const
char
*
,
void
*
),
void
*
data
);
void
(
*
free
)(
struct
git_config_file
*
);
void
(
*
free
)(
struct
git_config_file
*
);
};
};
...
@@ -314,6 +314,24 @@ GIT_EXTERN(int) git_config_foreach(
...
@@ -314,6 +314,24 @@ GIT_EXTERN(int) git_config_foreach(
int
(
*
callback
)(
const
char
*
var_name
,
const
char
*
value
,
void
*
payload
),
int
(
*
callback
)(
const
char
*
var_name
,
const
char
*
value
,
void
*
payload
),
void
*
payload
);
void
*
payload
);
/**
* Perform an operation on each config variable matching a regular expression.
*
* This behaviors like `git_config_foreach` with an additional filter of a
* regular expression that filters which config keys are passed to the
* callback.
*
* @param cfg where to get the variables from
* @param regexp regular expression to match against config names
* @param callback the function to call on each variable
* @param payload the data to pass to the callback
* @return 0 or the return value of the callback which didn't return 0
*/
GIT_EXTERN
(
int
)
git_config_foreach_match
(
git_config
*
cfg
,
const
char
*
regexp
,
int
(
*
callback
)(
const
char
*
var_name
,
const
char
*
value
,
void
*
payload
),
void
*
payload
);
/**
/**
* Query the value of a config variable and return it mapped to
* Query the value of a config variable and return it mapped to
...
...
include/git2/repository.h
View file @
48bcf81d
...
@@ -194,9 +194,12 @@ GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
...
@@ -194,9 +194,12 @@ GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
*
*
* @param repo A repository object
* @param repo A repository object
* @param workdir The path to a working directory
* @param workdir The path to a working directory
* @param update_gitlink Create/update gitlink in workdir and set config
* "core.worktree" (if workdir is not the parent of the .git directory)
* @return 0, or an error code
* @return 0, or an error code
*/
*/
GIT_EXTERN
(
int
)
git_repository_set_workdir
(
git_repository
*
repo
,
const
char
*
workdir
);
GIT_EXTERN
(
int
)
git_repository_set_workdir
(
git_repository
*
repo
,
const
char
*
workdir
,
int
update_gitlink
);
/**
/**
* Check if a repository is bare
* Check if a repository is bare
...
...
src/buffer.c
View file @
48bcf81d
...
@@ -141,6 +141,42 @@ int git_buf_puts(git_buf *buf, const char *string)
...
@@ -141,6 +141,42 @@ int git_buf_puts(git_buf *buf, const char *string)
return
git_buf_put
(
buf
,
string
,
strlen
(
string
));
return
git_buf_put
(
buf
,
string
,
strlen
(
string
));
}
}
int
git_buf_puts_escaped
(
git_buf
*
buf
,
const
char
*
string
,
const
char
*
esc_chars
,
const
char
*
esc_with
)
{
const
char
*
scan
=
string
;
size_t
total
=
0
,
esc_with_len
=
strlen
(
esc_with
);
while
(
*
scan
)
{
size_t
count
=
strcspn
(
scan
,
esc_chars
);
total
+=
count
+
1
+
esc_with_len
;
scan
+=
count
+
1
;
}
ENSURE_SIZE
(
buf
,
buf
->
size
+
total
+
1
);
for
(
scan
=
string
;
*
scan
;
)
{
size_t
count
=
strcspn
(
scan
,
esc_chars
);
memmove
(
buf
->
ptr
+
buf
->
size
,
scan
,
count
);
scan
+=
count
;
buf
->
size
+=
count
;
if
(
*
scan
)
{
memmove
(
buf
->
ptr
+
buf
->
size
,
esc_with
,
esc_with_len
);
buf
->
size
+=
esc_with_len
;
memmove
(
buf
->
ptr
+
buf
->
size
,
scan
,
1
);
scan
+=
1
;
buf
->
size
+=
1
;
}
}
buf
->
ptr
[
buf
->
size
]
=
'\0'
;
return
0
;
}
int
git_buf_vprintf
(
git_buf
*
buf
,
const
char
*
format
,
va_list
ap
)
int
git_buf_vprintf
(
git_buf
*
buf
,
const
char
*
format
,
va_list
ap
)
{
{
int
len
;
int
len
;
...
...
src/buffer.h
View file @
48bcf81d
...
@@ -91,6 +91,18 @@ int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...);
...
@@ -91,6 +91,18 @@ int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...);
int
git_buf_join
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
);
int
git_buf_join
(
git_buf
*
buf
,
char
separator
,
const
char
*
str_a
,
const
char
*
str_b
);
/**
/**
* Copy string into buf prefixing every character that is contained in the
* esc_chars string with the esc_with string.
*/
int
git_buf_puts_escaped
(
git_buf
*
buf
,
const
char
*
string
,
const
char
*
esc_chars
,
const
char
*
esc_with
);
GIT_INLINE
(
int
)
git_buf_puts_escape_regex
(
git_buf
*
buf
,
const
char
*
string
)
{
return
git_buf_puts_escaped
(
buf
,
string
,
"^.[]$()|*+?{}
\\
"
,
"
\\
"
);
}
/**
* Join two strings as paths, inserting a slash between as needed.
* Join two strings as paths, inserting a slash between as needed.
* @return 0 on success, -1 on failure
* @return 0 on success, -1 on failure
*/
*/
...
@@ -121,6 +133,13 @@ GIT_INLINE(ssize_t) git_buf_rfind_next(git_buf *buf, char ch)
...
@@ -121,6 +133,13 @@ GIT_INLINE(ssize_t) git_buf_rfind_next(git_buf *buf, char ch)
return
idx
;
return
idx
;
}
}
GIT_INLINE
(
ssize_t
)
git_buf_rfind
(
git_buf
*
buf
,
char
ch
)
{
ssize_t
idx
=
(
ssize_t
)
buf
->
size
-
1
;
while
(
idx
>=
0
&&
buf
->
ptr
[
idx
]
!=
ch
)
idx
--
;
return
idx
;
}
/* Remove whitespace from the end of the buffer */
/* Remove whitespace from the end of the buffer */
void
git_buf_rtrim
(
git_buf
*
buf
);
void
git_buf_rtrim
(
git_buf
*
buf
);
...
...
src/config.c
View file @
48bcf81d
...
@@ -136,17 +136,27 @@ int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
...
@@ -136,17 +136,27 @@ int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
* Loop over all the variables
* Loop over all the variables
*/
*/
int
git_config_foreach
(
git_config
*
cfg
,
int
(
*
fn
)(
const
char
*
,
const
char
*
,
void
*
),
void
*
data
)
int
git_config_foreach
(
git_config
*
cfg
,
int
(
*
fn
)(
const
char
*
,
const
char
*
,
void
*
),
void
*
data
)
{
return
git_config_foreach_match
(
cfg
,
NULL
,
fn
,
data
);
}
int
git_config_foreach_match
(
git_config
*
cfg
,
const
char
*
regexp
,
int
(
*
fn
)(
const
char
*
,
const
char
*
,
void
*
),
void
*
data
)
{
{
int
ret
=
0
;
int
ret
=
0
;
unsigned
int
i
;
unsigned
int
i
;
file_internal
*
internal
;
file_internal
*
internal
;
git_config_file
*
file
;
git_config_file
*
file
;
for
(
i
=
0
;
i
<
cfg
->
files
.
length
&&
ret
==
0
;
++
i
)
{
for
(
i
=
0
;
i
<
cfg
->
files
.
length
&&
ret
==
0
;
++
i
)
{
internal
=
git_vector_get
(
&
cfg
->
files
,
i
);
internal
=
git_vector_get
(
&
cfg
->
files
,
i
);
file
=
internal
->
file
;
file
=
internal
->
file
;
ret
=
file
->
foreach
(
file
,
fn
,
data
);
ret
=
file
->
foreach
(
file
,
regexp
,
fn
,
data
);
}
}
return
ret
;
return
ret
;
...
...
src/config_file.c
View file @
48bcf81d
...
@@ -188,25 +188,46 @@ static void backend_free(git_config_file *_backend)
...
@@ -188,25 +188,46 @@ static void backend_free(git_config_file *_backend)
git__free
(
backend
);
git__free
(
backend
);
}
}
static
int
file_foreach
(
git_config_file
*
backend
,
int
(
*
fn
)(
const
char
*
,
const
char
*
,
void
*
),
void
*
data
)
static
int
file_foreach
(
git_config_file
*
backend
,
const
char
*
regexp
,
int
(
*
fn
)(
const
char
*
,
const
char
*
,
void
*
),
void
*
data
)
{
{
diskfile_backend
*
b
=
(
diskfile_backend
*
)
backend
;
diskfile_backend
*
b
=
(
diskfile_backend
*
)
backend
;
cvar_t
*
var
;
cvar_t
*
var
;
const
char
*
key
;
const
char
*
key
;
regex_t
regex
;
int
result
=
0
;
if
(
!
b
->
values
)
if
(
!
b
->
values
)
return
0
;
return
0
;
if
(
regexp
!=
NULL
)
{
if
((
result
=
regcomp
(
&
regex
,
regexp
,
REG_EXTENDED
))
<
0
)
{
giterr_set_regex
(
&
regex
,
result
);
regfree
(
&
regex
);
return
-
1
;
}
}
git_strmap_foreach
(
b
->
values
,
key
,
var
,
git_strmap_foreach
(
b
->
values
,
key
,
var
,
do
{
for
(;
var
!=
NULL
;
var
=
CVAR_LIST_NEXT
(
var
))
{
if
(
fn
(
key
,
var
->
value
,
data
)
<
0
)
/* skip non-matching keys if regexp was provided */
break
;
if
(
regexp
&&
regexec
(
&
regex
,
key
,
0
,
NULL
,
0
)
!=
0
)
continue
;
var
=
CVAR_LIST_NEXT
(
var
);
/* abort iterator on non-zero return value */
}
while
(
var
!=
NULL
);
if
((
result
=
fn
(
key
,
var
->
value
,
data
))
!=
0
)
goto
cleanup
;
}
);
);
return
0
;
cleanup:
if
(
regexp
!=
NULL
)
regfree
(
&
regex
);
return
result
;
}
}
static
int
config_set
(
git_config_file
*
cfg
,
const
char
*
name
,
const
char
*
value
)
static
int
config_set
(
git_config_file
*
cfg
,
const
char
*
name
,
const
char
*
value
)
...
@@ -337,6 +358,7 @@ static int config_get_multivar(
...
@@ -337,6 +358,7 @@ static int config_get_multivar(
result
=
regcomp
(
&
regex
,
regex_str
,
REG_EXTENDED
);
result
=
regcomp
(
&
regex
,
regex_str
,
REG_EXTENDED
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
giterr_set_regex
(
&
regex
,
result
);
giterr_set_regex
(
&
regex
,
result
);
regfree
(
&
regex
);
return
-
1
;
return
-
1
;
}
}
...
@@ -396,6 +418,7 @@ static int config_set_multivar(
...
@@ -396,6 +418,7 @@ static int config_set_multivar(
if
(
result
<
0
)
{
if
(
result
<
0
)
{
git__free
(
key
);
git__free
(
key
);
giterr_set_regex
(
&
preg
,
result
);
giterr_set_regex
(
&
preg
,
result
);
regfree
(
&
preg
);
return
-
1
;
return
-
1
;
}
}
...
...
src/config_file.h
View file @
48bcf81d
...
@@ -19,12 +19,27 @@ GIT_INLINE(void) git_config_file_free(git_config_file *cfg)
...
@@ -19,12 +19,27 @@ GIT_INLINE(void) git_config_file_free(git_config_file *cfg)
cfg
->
free
(
cfg
);
cfg
->
free
(
cfg
);
}
}
GIT_INLINE
(
int
)
git_config_file_set_string
(
git_config_file
*
cfg
,
const
char
*
name
,
const
char
*
value
)
{
return
cfg
->
set
(
cfg
,
name
,
value
);
}
GIT_INLINE
(
int
)
git_config_file_foreach
(
GIT_INLINE
(
int
)
git_config_file_foreach
(
git_config_file
*
cfg
,
git_config_file
*
cfg
,
int
(
*
fn
)(
const
char
*
key
,
const
char
*
value
,
void
*
data
),
int
(
*
fn
)(
const
char
*
key
,
const
char
*
value
,
void
*
data
),
void
*
data
)
void
*
data
)
{
{
return
cfg
->
foreach
(
cfg
,
fn
,
data
);
return
cfg
->
foreach
(
cfg
,
NULL
,
fn
,
data
);
}
GIT_INLINE
(
int
)
git_config_file_foreach_match
(
git_config_file
*
cfg
,
const
char
*
regexp
,
int
(
*
fn
)(
const
char
*
key
,
const
char
*
value
,
void
*
data
),
void
*
data
)
{
return
cfg
->
foreach
(
cfg
,
regexp
,
fn
,
data
);
}
}
#endif
#endif
...
...
src/path.c
View file @
48bcf81d
...
@@ -17,9 +17,7 @@
...
@@ -17,9 +17,7 @@
#include <stdio.h>
#include <stdio.h>
#include <ctype.h>
#include <ctype.h>
#ifdef GIT_WIN32
#define LOOKS_LIKE_DRIVE_PREFIX(S) (git__isalpha((S)[0]) && (S)[1] == ':')
#define LOOKS_LIKE_DRIVE_PREFIX(S) (git__isalpha((S)[0]) && (S)[1] == ':')
#endif
/*
/*
* Based on the Android implementation, BSD licensed.
* Based on the Android implementation, BSD licensed.
...
@@ -172,11 +170,11 @@ int git_path_root(const char *path)
...
@@ -172,11 +170,11 @@ int git_path_root(const char *path)
{
{
int
offset
=
0
;
int
offset
=
0
;
#ifdef GIT_WIN32
/* Does the root of the path look like a windows drive ? */
/* Does the root of the path look like a windows drive ? */
if
(
LOOKS_LIKE_DRIVE_PREFIX
(
path
))
if
(
LOOKS_LIKE_DRIVE_PREFIX
(
path
))
offset
+=
2
;
offset
+=
2
;
#ifdef GIT_WIN32
/* Are we dealing with a windows network path? */
/* Are we dealing with a windows network path? */
else
if
((
path
[
0
]
==
'/'
&&
path
[
1
]
==
'/'
)
||
else
if
((
path
[
0
]
==
'/'
&&
path
[
1
]
==
'/'
)
||
(
path
[
0
]
==
'\\'
&&
path
[
1
]
==
'\\'
))
(
path
[
0
]
==
'\\'
&&
path
[
1
]
==
'\\'
))
...
@@ -464,6 +462,71 @@ int git_path_find_dir(git_buf *dir, const char *path, const char *base)
...
@@ -464,6 +462,71 @@ int git_path_find_dir(git_buf *dir, const char *path, const char *base)
return
error
;
return
error
;
}
}
int
git_path_resolve_relative
(
git_buf
*
path
,
size_t
ceiling
)
{
char
*
base
,
*
to
,
*
from
,
*
next
;
size_t
len
;
if
(
!
path
||
git_buf_oom
(
path
))
return
-
1
;
if
(
ceiling
>
path
->
size
)
ceiling
=
path
->
size
;
/* recognize drive prefixes, etc. that should not be backed over */
if
(
ceiling
==
0
)
ceiling
=
git_path_root
(
path
->
ptr
)
+
1
;
/* recognize URL prefixes that should not be backed over */
if
(
ceiling
==
0
)
{
for
(
next
=
path
->
ptr
;
*
next
&&
git__isalpha
(
*
next
);
++
next
);
if
(
next
[
0
]
==
':'
&&
next
[
1
]
==
'/'
&&
next
[
2
]
==
'/'
)
ceiling
=
(
next
+
3
)
-
path
->
ptr
;
}
base
=
to
=
from
=
path
->
ptr
+
ceiling
;
while
(
*
from
)
{
for
(
next
=
from
;
*
next
&&
*
next
!=
'/'
;
++
next
);
len
=
next
-
from
;
if
(
len
==
1
&&
from
[
0
]
==
'.'
)
/* do nothing with singleton dot */
;
else
if
(
len
==
2
&&
from
[
0
]
==
'.'
&&
from
[
1
]
==
'.'
)
{
while
(
to
>
base
&&
to
[
-
1
]
==
'/'
)
to
--
;
while
(
to
>
base
&&
to
[
-
1
]
!=
'/'
)
to
--
;
}
else
{
if
(
*
next
==
'/'
)
len
++
;
if
(
to
!=
from
)
memmove
(
to
,
from
,
len
);
to
+=
len
;
}
from
+=
len
;
while
(
*
from
==
'/'
)
from
++
;
}
*
to
=
'\0'
;
path
->
size
=
to
-
path
->
ptr
;
return
0
;
}
int
git_path_apply_relative
(
git_buf
*
target
,
const
char
*
relpath
)
{
git_buf_joinpath
(
target
,
git_buf_cstr
(
target
),
relpath
);
return
git_path_resolve_relative
(
target
,
0
);
}
int
git_path_cmp
(
int
git_path_cmp
(
const
char
*
name1
,
size_t
len1
,
int
isdir1
,
const
char
*
name1
,
size_t
len1
,
int
isdir1
,
const
char
*
name2
,
size_t
len2
,
int
isdir2
)
const
char
*
name2
,
size_t
len2
,
int
isdir2
)
...
...
src/path.h
View file @
48bcf81d
...
@@ -186,6 +186,29 @@ extern int git_path_prettify_dir(git_buf *path_out, const char *path, const char
...
@@ -186,6 +186,29 @@ extern int git_path_prettify_dir(git_buf *path_out, const char *path, const char
extern
int
git_path_find_dir
(
git_buf
*
dir
,
const
char
*
path
,
const
char
*
base
);
extern
int
git_path_find_dir
(
git_buf
*
dir
,
const
char
*
path
,
const
char
*
base
);
/**
/**
* Resolve relative references within a path.
*
* This eliminates "./" and "../" relative references inside a path,
* as well as condensing multiple slashes into single ones. It will
* not touch the path before the "ceiling" length.
*
* Additionally, this will recognize an "c:/" drive prefix or a "xyz://" URL
* prefix and not touch that part of the path.
*/
extern
int
git_path_resolve_relative
(
git_buf
*
path
,
size_t
ceiling
);
/**
* Apply a relative path to base path.
*
* Note that the base path could be a filename or a URL and this
* should still work. The relative path is walked segment by segment
* with three rules: series of slashes will be condensed to a single
* slash, "." will be eaten with no change, and ".." will remove a
* segment from the base path.
*/
extern
int
git_path_apply_relative
(
git_buf
*
target
,
const
char
*
relpath
);
/**
* Walk each directory entry, except '.' and '..', calling fn(state).
* Walk each directory entry, except '.' and '..', calling fn(state).
*
*
* @param pathbuf buffer the function reads the initial directory
* @param pathbuf buffer the function reads the initial directory
...
...
src/repository.c
View file @
48bcf81d
...
@@ -741,15 +741,24 @@ static int repo_init_config(const char *git_dir, bool is_bare, bool is_reinit)
...
@@ -741,15 +741,24 @@ static int repo_init_config(const char *git_dir, bool is_bare, bool is_reinit)
#define GIT_DESC_CONTENT "Unnamed repository; edit this file 'description' to name the repository.\n"
#define GIT_DESC_CONTENT "Unnamed repository; edit this file 'description' to name the repository.\n"
static
int
repo_write_template
(
static
int
repo_write_template
(
const
char
*
git_dir
,
const
char
*
file
,
mode_t
mode
,
const
char
*
content
)
const
char
*
git_dir
,
bool
allow_overwrite
,
const
char
*
file
,
mode_t
mode
,
const
char
*
content
)
{
{
git_buf
path
=
GIT_BUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
int
fd
,
error
=
0
;
int
fd
,
error
=
0
,
flags
;
if
(
git_buf_joinpath
(
&
path
,
git_dir
,
file
)
<
0
)
if
(
git_buf_joinpath
(
&
path
,
git_dir
,
file
)
<
0
)
return
-
1
;
return
-
1
;
fd
=
p_open
(
git_buf_cstr
(
&
path
),
O_WRONLY
|
O_CREAT
|
O_EXCL
,
mode
);
if
(
allow_overwrite
)
flags
=
O_WRONLY
|
O_CREAT
|
O_TRUNC
;
else
flags
=
O_WRONLY
|
O_CREAT
|
O_EXCL
;
fd
=
p_open
(
git_buf_cstr
(
&
path
),
flags
,
mode
);
if
(
fd
>=
0
)
{
if
(
fd
>=
0
)
{
error
=
p_write
(
fd
,
content
,
strlen
(
content
));
error
=
p_write
(
fd
,
content
,
strlen
(
content
));
...
@@ -811,7 +820,7 @@ static int repo_init_structure(const char *git_dir, int is_bare)
...
@@ -811,7 +820,7 @@ static int repo_init_structure(const char *git_dir, int is_bare)
/* Make template files as needed */
/* Make template files as needed */
for
(
i
=
0
;
tmpl
[
i
].
file
!=
NULL
;
++
i
)
{
for
(
i
=
0
;
tmpl
[
i
].
file
!=
NULL
;
++
i
)
{
if
(
repo_write_template
(
if
(
repo_write_template
(
git_dir
,
tmpl
[
i
].
file
,
tmpl
[
i
].
mode
,
tmpl
[
i
].
content
)
<
0
)
git_dir
,
false
,
tmpl
[
i
].
file
,
tmpl
[
i
].
mode
,
tmpl
[
i
].
content
)
<
0
)
return
-
1
;
return
-
1
;
}
}
...
@@ -943,8 +952,47 @@ const char *git_repository_workdir(git_repository *repo)
...
@@ -943,8 +952,47 @@ const char *git_repository_workdir(git_repository *repo)
return
repo
->
workdir
;
return
repo
->
workdir
;
}
}
int
git_repository_set_workdir
(
git_repository
*
repo
,
const
char
*
workdir
)
static
int
write_gitlink
(
const
char
*
in_dir
,
const
char
*
to_repo
)
{
int
error
;
git_buf
buf
=
GIT_BUF_INIT
;
struct
stat
st
;
if
(
git_path_dirname_r
(
&
buf
,
to_repo
)
<
0
||
git_path_to_dir
(
&
buf
)
<
0
)
return
-
1
;
/* don't write gitlink to natural workdir */
if
(
git__suffixcmp
(
to_repo
,
"/"
DOT_GIT
"/"
)
==
0
&&
strcmp
(
in_dir
,
buf
.
ptr
)
==
0
)
return
GIT_PASSTHROUGH
;
if
(
git_buf_joinpath
(
&
buf
,
in_dir
,
DOT_GIT
)
<
0
)
return
-
1
;
if
(
!
p_stat
(
buf
.
ptr
,
&
st
)
&&
!
S_ISREG
(
st
.
st_mode
))
{
giterr_set
(
GITERR_REPOSITORY
,
"Cannot overwrite gitlink file into path '%s'"
,
in_dir
);
return
GIT_EEXISTS
;
}
git_buf_clear
(
&
buf
);
if
(
git_buf_printf
(
&
buf
,
"%s %s"
,
GIT_FILE_CONTENT_PREFIX
,
to_repo
)
<
0
)
return
-
1
;
error
=
repo_write_template
(
in_dir
,
true
,
DOT_GIT
,
0644
,
buf
.
ptr
);
git_buf_free
(
&
buf
);
return
error
;
}
int
git_repository_set_workdir
(
git_repository
*
repo
,
const
char
*
workdir
,
int
update_gitlink
)
{
{
int
error
=
0
;
git_buf
path
=
GIT_BUF_INIT
;
git_buf
path
=
GIT_BUF_INIT
;
assert
(
repo
&&
workdir
);
assert
(
repo
&&
workdir
);
...
@@ -952,11 +1000,37 @@ int git_repository_set_workdir(git_repository *repo, const char *workdir)
...
@@ -952,11 +1000,37 @@ int git_repository_set_workdir(git_repository *repo, const char *workdir)
if
(
git_path_prettify_dir
(
&
path
,
workdir
,
NULL
)
<
0
)
if
(
git_path_prettify_dir
(
&
path
,
workdir
,
NULL
)
<
0
)
return
-
1
;
return
-
1
;
git__free
(
repo
->
workdir
);
if
(
repo
->
workdir
&&
strcmp
(
repo
->
workdir
,
path
.
ptr
)
==
0
)
return
0
;
repo
->
workdir
=
git_buf_detach
(
&
path
);
if
(
update_gitlink
)
{
repo
->
is_bare
=
0
;
git_config
*
config
;
return
0
;
if
(
git_repository_config__weakptr
(
&
config
,
repo
)
<
0
)
return
-
1
;
error
=
write_gitlink
(
path
.
ptr
,
git_repository_path
(
repo
));
/* passthrough error means gitlink is unnecessary */
if
(
error
==
GIT_PASSTHROUGH
)
error
=
git_config_delete
(
config
,
"core.worktree"
);
else
if
(
!
error
)
error
=
git_config_set_string
(
config
,
"core.worktree"
,
path
.
ptr
);
if
(
!
error
)
error
=
git_config_set_bool
(
config
,
"core.bare"
,
false
);
}
if
(
!
error
)
{
char
*
old_workdir
=
repo
->
workdir
;
repo
->
workdir
=
git_buf_detach
(
&
path
);
repo
->
is_bare
=
0
;
git__free
(
old_workdir
);
}
return
error
;
}
}
int
git_repository_is_bare
(
git_repository
*
repo
)
int
git_repository_is_bare
(
git_repository
*
repo
)
...
...
src/util.h
View file @
48bcf81d
...
@@ -211,7 +211,7 @@ GIT_INLINE(bool) git__isdigit(int c)
...
@@ -211,7 +211,7 @@ GIT_INLINE(bool) git__isdigit(int c)
GIT_INLINE
(
bool
)
git__isspace
(
int
c
)
GIT_INLINE
(
bool
)
git__isspace
(
int
c
)
{
{
return
(
c
==
' '
||
c
==
'\t'
||
c
==
'\n'
||
c
==
'\f'
||
c
==
'\r'
||
c
==
'\v'
);
return
(
c
==
' '
||
c
==
'\t'
||
c
==
'\n'
||
c
==
'\f'
||
c
==
'\r'
||
c
==
'\v'
||
c
==
0x85
/* Unicode CR+LF */
);
}
}
GIT_INLINE
(
bool
)
git__iswildcard
(
int
c
)
GIT_INLINE
(
bool
)
git__iswildcard
(
int
c
)
...
...
tests-clar/config/read.c
View file @
48bcf81d
...
@@ -191,6 +191,81 @@ void test_config_read__escaping_quotes(void)
...
@@ -191,6 +191,81 @@ void test_config_read__escaping_quotes(void)
git_config_free
(
cfg
);
git_config_free
(
cfg
);
}
}
static
int
count_cfg_entries
(
const
char
*
var_name
,
const
char
*
value
,
void
*
payload
)
{
int
*
count
=
payload
;
GIT_UNUSED
(
var_name
);
GIT_UNUSED
(
value
);
(
*
count
)
++
;
return
0
;
}
static
int
cfg_callback_countdown
(
const
char
*
var_name
,
const
char
*
value
,
void
*
payload
)
{
int
*
count
=
payload
;
GIT_UNUSED
(
var_name
);
GIT_UNUSED
(
value
);
(
*
count
)
--
;
if
(
*
count
==
0
)
return
-
100
;
return
0
;
}
void
test_config_read__foreach
(
void
)
{
git_config
*
cfg
;
int
count
,
ret
;
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
cl_fixture
(
"config/config9"
)));
count
=
0
;
cl_git_pass
(
git_config_foreach
(
cfg
,
count_cfg_entries
,
&
count
));
cl_assert_equal_i
(
5
,
count
);
count
=
3
;
cl_git_fail
(
ret
=
git_config_foreach
(
cfg
,
cfg_callback_countdown
,
&
count
));
cl_assert_equal_i
(
-
100
,
ret
);
git_config_free
(
cfg
);
}
void
test_config_read__foreach_match
(
void
)
{
git_config
*
cfg
;
int
count
;
cl_git_pass
(
git_config_open_ondisk
(
&
cfg
,
cl_fixture
(
"config/config9"
)));
count
=
0
;
cl_git_pass
(
git_config_foreach_match
(
cfg
,
"core.*"
,
count_cfg_entries
,
&
count
));
cl_assert_equal_i
(
3
,
count
);
count
=
0
;
cl_git_pass
(
git_config_foreach_match
(
cfg
,
"remote
\\
.ab.*"
,
count_cfg_entries
,
&
count
));
cl_assert_equal_i
(
2
,
count
);
count
=
0
;
cl_git_pass
(
git_config_foreach_match
(
cfg
,
".*url$"
,
count_cfg_entries
,
&
count
));
cl_assert_equal_i
(
2
,
count
);
count
=
0
;
cl_git_pass
(
git_config_foreach_match
(
cfg
,
".*dummy.*"
,
count_cfg_entries
,
&
count
));
cl_assert_equal_i
(
2
,
count
);
count
=
0
;
cl_git_pass
(
git_config_foreach_match
(
cfg
,
".*nomatch.*"
,
count_cfg_entries
,
&
count
));
cl_assert_equal_i
(
0
,
count
);
git_config_free
(
cfg
);
}
#if 0
#if 0
BEGIN_TEST(config10, "a repo's config overrides the global config")
BEGIN_TEST(config10, "a repo's config overrides the global config")
...
...
tests-clar/core/buffer.c
View file @
48bcf81d
...
@@ -611,3 +611,50 @@ void test_core_buffer__11(void)
...
@@ -611,3 +611,50 @@ void test_core_buffer__11(void)
git_buf_free
(
&
a
);
git_buf_free
(
&
a
);
}
}
void
test_core_buffer__rfind_variants
(
void
)
{
git_buf
a
=
GIT_BUF_INIT
;
ssize_t
len
;
cl_git_pass
(
git_buf_sets
(
&
a
,
"/this/is/it/"
));
len
=
(
ssize_t
)
git_buf_len
(
&
a
);
cl_assert
(
git_buf_rfind
(
&
a
,
'/'
)
==
len
-
1
);
cl_assert
(
git_buf_rfind_next
(
&
a
,
'/'
)
==
len
-
4
);
cl_assert
(
git_buf_rfind
(
&
a
,
'i'
)
==
len
-
3
);
cl_assert
(
git_buf_rfind_next
(
&
a
,
'i'
)
==
len
-
3
);
cl_assert
(
git_buf_rfind
(
&
a
,
'h'
)
==
2
);
cl_assert
(
git_buf_rfind_next
(
&
a
,
'h'
)
==
2
);
cl_assert
(
git_buf_rfind
(
&
a
,
'q'
)
==
-
1
);
cl_assert
(
git_buf_rfind_next
(
&
a
,
'q'
)
==
-
1
);
git_buf_clear
(
&
a
);
}
void
test_core_buffer__puts_escaped
(
void
)
{
git_buf
a
=
GIT_BUF_INIT
;
git_buf_clear
(
&
a
);
cl_git_pass
(
git_buf_puts_escaped
(
&
a
,
"this is a test"
,
""
,
""
));
cl_assert_equal_s
(
"this is a test"
,
a
.
ptr
);
git_buf_clear
(
&
a
);
cl_git_pass
(
git_buf_puts_escaped
(
&
a
,
"this is a test"
,
"t"
,
"
\\
"
));
cl_assert_equal_s
(
"
\\
this is a
\\
tes
\\
t"
,
a
.
ptr
);
git_buf_clear
(
&
a
);
cl_git_pass
(
git_buf_puts_escaped
(
&
a
,
"this is a test"
,
"i "
,
"__"
));
cl_assert_equal_s
(
"th__is__ __is__ a__ test"
,
a
.
ptr
);
git_buf_clear
(
&
a
);
cl_git_pass
(
git_buf_puts_escape_regex
(
&
a
,
"^match
\\
s*[A-Z]+.*"
));
cl_assert_equal_s
(
"
\\
^match
\\\\
s
\\
*
\\
[A-Z
\\
]
\\
+
\\
.
\\
*"
,
a
.
ptr
);
git_buf_free
(
&
a
);
}
tests-clar/core/path.c
View file @
48bcf81d
...
@@ -418,3 +418,54 @@ void test_core_path__13_cannot_prettify_a_non_existing_file(void)
...
@@ -418,3 +418,54 @@ void test_core_path__13_cannot_prettify_a_non_existing_file(void)
git_buf_free
(
&
p
);
git_buf_free
(
&
p
);
}
}
void
test_core_path__14_apply_relative
(
void
)
{
git_buf
p
=
GIT_BUF_INIT
;
cl_git_pass
(
git_buf_sets
(
&
p
,
"/this/is/a/base"
));
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../test"
));
cl_assert_equal_s
(
"/this/is/a/test"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../../the/./end"
));
cl_assert_equal_s
(
"/this/is/the/end"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"./of/this/../the/string"
));
cl_assert_equal_s
(
"/this/is/the/end/of/the/string"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../../../../../.."
));
cl_assert_equal_s
(
"/this/"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../../../../../"
));
cl_assert_equal_s
(
"/"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../../../../.."
));
cl_assert_equal_s
(
"/"
,
p
.
ptr
);
cl_git_pass
(
git_buf_sets
(
&
p
,
"d:/another/test"
));
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../../../../.."
));
cl_assert_equal_s
(
"d:/"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"from/here/to/../and/./back/."
));
cl_assert_equal_s
(
"d:/from/here/and/back/"
,
p
.
ptr
);
cl_git_pass
(
git_buf_sets
(
&
p
,
"https://my.url.com/test.git"
));
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../another.git"
));
cl_assert_equal_s
(
"https://my.url.com/another.git"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../full/path/url.patch"
));
cl_assert_equal_s
(
"https://my.url.com/full/path/url.patch"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
".."
));
cl_assert_equal_s
(
"https://my.url.com/full/path/"
,
p
.
ptr
);
cl_git_pass
(
git_path_apply_relative
(
&
p
,
"../../../../../"
));
cl_assert_equal_s
(
"https://"
,
p
.
ptr
);
git_buf_free
(
&
p
);
}
tests-clar/repo/setters.c
View file @
48bcf81d
...
@@ -2,6 +2,8 @@
...
@@ -2,6 +2,8 @@
#include "buffer.h"
#include "buffer.h"
#include "posix.h"
#include "posix.h"
#include "util.h"
#include "util.h"
#include "path.h"
#include "fileops.h"
static
git_repository
*
repo
;
static
git_repository
*
repo
;
...
@@ -16,7 +18,7 @@ void test_repo_setters__cleanup(void)
...
@@ -16,7 +18,7 @@ void test_repo_setters__cleanup(void)
{
{
git_repository_free
(
repo
);
git_repository_free
(
repo
);
cl_fixture_cleanup
(
"testrepo.git"
);
cl_fixture_cleanup
(
"testrepo.git"
);
cl_
must_pass
(
p_rmdir
(
"new_workdir"
)
);
cl_
fixture_cleanup
(
"new_workdir"
);
}
}
void
test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standard_one
(
void
)
void
test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standard_one
(
void
)
...
@@ -24,7 +26,7 @@ void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standar
...
@@ -24,7 +26,7 @@ void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standar
cl_assert
(
git_repository_is_bare
(
repo
)
==
1
);
cl_assert
(
git_repository_is_bare
(
repo
)
==
1
);
cl_assert
(
git_repository_workdir
(
repo
)
==
NULL
);
cl_assert
(
git_repository_workdir
(
repo
)
==
NULL
);
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"./new_workdir"
));
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"./new_workdir"
,
false
));
cl_assert
(
git_repository_workdir
(
repo
)
!=
NULL
);
cl_assert
(
git_repository_workdir
(
repo
)
!=
NULL
);
cl_assert
(
git_repository_is_bare
(
repo
)
==
0
);
cl_assert
(
git_repository_is_bare
(
repo
)
==
0
);
...
@@ -32,9 +34,30 @@ void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standar
...
@@ -32,9 +34,30 @@ void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standar
void
test_repo_setters__setting_a_workdir_prettifies_its_path
(
void
)
void
test_repo_setters__setting_a_workdir_prettifies_its_path
(
void
)
{
{
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"./new_workdir"
));
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"./new_workdir"
,
false
));
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo
),
"/"
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_repository_workdir
(
repo
),
"new_workdir/"
)
==
0
);
}
void
test_repo_setters__setting_a_workdir_creates_a_gitlink
(
void
)
{
git_config
*
cfg
;
const
char
*
val
;
git_buf
content
=
GIT_BUF_INIT
;
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"./new_workdir"
,
true
));
cl_assert
(
git_path_isfile
(
"./new_workdir/.git"
));
cl_git_pass
(
git_futils_readbuffer
(
&
content
,
"./new_workdir/.git"
));
cl_assert
(
git__prefixcmp
(
git_buf_cstr
(
&
content
),
"gitdir: "
)
==
0
);
cl_assert
(
git__suffixcmp
(
git_buf_cstr
(
&
content
),
"testrepo.git/"
)
==
0
);
git_buf_free
(
&
content
);
cl_git_pass
(
git_repository_config
(
&
cfg
,
repo
));
cl_git_pass
(
git_config_get_string
(
&
val
,
cfg
,
"core.worktree"
));
cl_assert
(
git__suffixcmp
(
val
,
"new_workdir/"
)
==
0
);
git_config_free
(
cfg
);
}
}
void
test_repo_setters__setting_a_new_index_on_a_repo_which_has_already_loaded_one_properly_honors_the_refcount
(
void
)
void
test_repo_setters__setting_a_new_index_on_a_repo_which_has_already_loaded_one_properly_honors_the_refcount
(
void
)
...
...
tests-clar/status/worktree.c
View file @
48bcf81d
...
@@ -459,7 +459,7 @@ void test_status_worktree__status_file_without_index_or_workdir(void)
...
@@ -459,7 +459,7 @@ void test_status_worktree__status_file_without_index_or_workdir(void)
cl_git_pass
(
p_mkdir
(
"wd"
,
0777
));
cl_git_pass
(
p_mkdir
(
"wd"
,
0777
));
cl_git_pass
(
git_repository_open
(
&
repo
,
cl_fixture
(
"testrepo.git"
)));
cl_git_pass
(
git_repository_open
(
&
repo
,
cl_fixture
(
"testrepo.git"
)));
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"wd"
));
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"wd"
,
false
));
cl_git_pass
(
git_index_open
(
&
index
,
"empty-index"
));
cl_git_pass
(
git_index_open
(
&
index
,
"empty-index"
));
cl_assert_equal_i
(
0
,
git_index_entrycount
(
index
));
cl_assert_equal_i
(
0
,
git_index_entrycount
(
index
));
...
@@ -500,7 +500,7 @@ void test_status_worktree__status_file_with_clean_index_and_empty_workdir(void)
...
@@ -500,7 +500,7 @@ void test_status_worktree__status_file_with_clean_index_and_empty_workdir(void)
cl_git_pass
(
p_mkdir
(
"wd"
,
0777
));
cl_git_pass
(
p_mkdir
(
"wd"
,
0777
));
cl_git_pass
(
git_repository_open
(
&
repo
,
cl_fixture
(
"testrepo.git"
)));
cl_git_pass
(
git_repository_open
(
&
repo
,
cl_fixture
(
"testrepo.git"
)));
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"wd"
));
cl_git_pass
(
git_repository_set_workdir
(
repo
,
"wd"
,
false
));
cl_git_pass
(
git_index_open
(
&
index
,
"my-index"
));
cl_git_pass
(
git_index_open
(
&
index
,
"my-index"
));
fill_index_wth_head_entries
(
repo
,
index
);
fill_index_wth_head_entries
(
repo
,
index
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment