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
4f24a932
Unverified
Commit
4f24a932
authored
Sep 14, 2021
by
Edward Thomson
Committed by
GitHub
Sep 14, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6031 from libgit2/ethomson/extensions
Support custom git extensions
parents
5bd49aee
a24e656a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
276 additions
and
46 deletions
+276
-46
include/git2/common.h
+19
-1
src/libgit2.c
+23
-0
src/repository.c
+112
-3
src/repository.h
+4
-0
tests/core/opts.c
+46
-0
tests/repo/extensions.c
+72
-0
tests/repo/open.c
+0
-42
No files found.
include/git2/common.h
View file @
4f24a932
...
...
@@ -209,7 +209,9 @@ typedef enum {
GIT_OPT_GET_MWINDOW_FILE_LIMIT
,
GIT_OPT_SET_MWINDOW_FILE_LIMIT
,
GIT_OPT_SET_ODB_PACKED_PRIORITY
,
GIT_OPT_SET_ODB_LOOSE_PRIORITY
GIT_OPT_SET_ODB_LOOSE_PRIORITY
,
GIT_OPT_GET_EXTENSIONS
,
GIT_OPT_SET_EXTENSIONS
}
git_libgit2_opt_t
;
/**
...
...
@@ -431,6 +433,22 @@ typedef enum {
* > Override the default priority of the loose ODB backend which
* > is added when default backends are assigned to a repository
*
* opts(GIT_OPT_GET_EXTENSIONS, git_strarray *out)
* > Returns the list of git extensions that are supported. This
* > is the list of built-in extensions supported by libgit2 and
* > custom extensions that have been added with
* > `GIT_OPT_SET_EXTENSIONS`. Extensions that have been negated
* > will not be returned. The returned list should be released
* > with `git_strarray_dispose`.
*
* opts(GIT_OPT_SET_EXTENSIONS, const char **extensions, size_t len)
* > Set that the given git extensions are supported by the caller.
* > Extensions supported by libgit2 may be negated by prefixing
* > them with a `!`. For example: setting extensions to
* > { "!noop", "newext" } indicates that the caller does not want
* > to support repositories with the `noop` extension but does want
* > to support repositories with the `newext` extension.
*
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
...
...
src/libgit2.c
View file @
4f24a932
...
...
@@ -52,6 +52,7 @@ static void libgit2_settings_global_shutdown(void)
{
git__free
(
git__user_agent
);
git__free
(
git__ssl_ciphers
);
git_repository__free_extensions
();
}
static
int
git_libgit2_settings_global_init
(
void
)
...
...
@@ -367,6 +368,28 @@ int git_libgit2_opts(int key, ...)
git_odb__loose_priority
=
va_arg
(
ap
,
int
);
break
;
case
GIT_OPT_SET_EXTENSIONS
:
{
const
char
**
extensions
=
va_arg
(
ap
,
const
char
**
);
size_t
len
=
va_arg
(
ap
,
size_t
);
error
=
git_repository__set_extensions
(
extensions
,
len
);
}
break
;
case
GIT_OPT_GET_EXTENSIONS
:
{
git_strarray
*
out
=
va_arg
(
ap
,
git_strarray
*
);
char
**
extensions
;
size_t
len
;
if
((
error
=
git_repository__extensions
(
&
extensions
,
&
len
))
<
0
)
break
;
out
->
strings
=
extensions
;
out
->
count
=
len
;
}
break
;
default:
git_error_set
(
GIT_ERROR_INVALID
,
"invalid option key"
);
error
=
-
1
;
...
...
src/repository.c
View file @
4f24a932
...
...
@@ -1427,15 +1427,60 @@ static int check_repositoryformatversion(int *version, git_config *config)
return
0
;
}
static
const
char
*
builtin_extensions
[]
=
{
"noop"
};
static
git_vector
user_extensions
=
GIT_VECTOR_INIT
;
static
int
check_valid_extension
(
const
git_config_entry
*
entry
,
void
*
payload
)
{
git_buf
cfg
=
GIT_BUF_INIT
;
bool
reject
;
const
char
*
extension
;
size_t
i
;
int
error
=
0
;
GIT_UNUSED
(
payload
);
if
(
!
strcmp
(
entry
->
name
,
"extensions.noop"
))
return
0
;
git_vector_foreach
(
&
user_extensions
,
i
,
extension
)
{
git_buf_clear
(
&
cfg
);
/*
* Users can specify that they don't want to support an
* extension with a '!' prefix.
*/
if
((
reject
=
(
extension
[
0
]
==
'!'
))
==
true
)
extension
=
&
extension
[
1
];
if
((
error
=
git_buf_printf
(
&
cfg
,
"extensions.%s"
,
extension
))
<
0
)
goto
done
;
if
(
strcmp
(
entry
->
name
,
cfg
.
ptr
)
==
0
)
{
if
(
reject
)
goto
fail
;
goto
done
;
}
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
builtin_extensions
);
i
++
)
{
extension
=
builtin_extensions
[
i
];
if
((
error
=
git_buf_printf
(
&
cfg
,
"extensions.%s"
,
extension
))
<
0
)
goto
done
;
if
(
strcmp
(
entry
->
name
,
cfg
.
ptr
)
==
0
)
goto
done
;
}
fail:
git_error_set
(
GIT_ERROR_REPOSITORY
,
"unsupported extension name %s"
,
entry
->
name
);
return
-
1
;
error
=
-
1
;
done:
git_buf_dispose
(
&
cfg
);
return
error
;
}
static
int
check_extensions
(
git_config
*
config
,
int
version
)
...
...
@@ -1446,6 +1491,70 @@ static int check_extensions(git_config *config, int version)
return
git_config_foreach_match
(
config
,
"^extensions
\\
."
,
check_valid_extension
,
NULL
);
}
int
git_repository__extensions
(
char
***
out
,
size_t
*
out_len
)
{
git_vector
extensions
;
const
char
*
builtin
,
*
user
;
char
*
extension
;
size_t
i
,
j
;
if
(
git_vector_init
(
&
extensions
,
8
,
NULL
)
<
0
)
return
-
1
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
builtin_extensions
);
i
++
)
{
bool
match
=
false
;
builtin
=
builtin_extensions
[
i
];
git_vector_foreach
(
&
user_extensions
,
j
,
user
)
{
if
(
user
[
0
]
==
'!'
&&
strcmp
(
builtin
,
&
user
[
1
])
==
0
)
{
match
=
true
;
break
;
}
}
if
(
match
)
continue
;
if
((
extension
=
git__strdup
(
builtin
))
==
NULL
||
git_vector_insert
(
&
extensions
,
extension
)
<
0
)
return
-
1
;
}
git_vector_foreach
(
&
user_extensions
,
i
,
user
)
{
if
(
user
[
0
]
==
'!'
)
continue
;
if
((
extension
=
git__strdup
(
user
))
==
NULL
||
git_vector_insert
(
&
extensions
,
extension
)
<
0
)
return
-
1
;
}
*
out
=
(
char
**
)
git_vector_detach
(
out_len
,
NULL
,
&
extensions
);
return
0
;
}
int
git_repository__set_extensions
(
const
char
**
extensions
,
size_t
len
)
{
char
*
extension
;
size_t
i
;
git_repository__free_extensions
();
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
((
extension
=
git__strdup
(
extensions
[
i
]))
==
NULL
||
git_vector_insert
(
&
user_extensions
,
extension
)
<
0
)
return
-
1
;
}
return
0
;
}
void
git_repository__free_extensions
(
void
)
{
git_vector_free_deep
(
&
user_extensions
);
}
int
git_repository_create_head
(
const
char
*
git_dir
,
const
char
*
ref_name
)
{
git_buf
ref_path
=
GIT_BUF_INIT
;
...
...
src/repository.h
View file @
4f24a932
...
...
@@ -249,4 +249,8 @@ int git_repository_initialbranch(git_buf *out, git_repository *repo);
*/
int
git_repository_workdir_path
(
git_buf
*
out
,
git_repository
*
repo
,
const
char
*
path
);
int
git_repository__extensions
(
char
***
out
,
size_t
*
out_len
);
int
git_repository__set_extensions
(
const
char
**
extensions
,
size_t
len
);
void
git_repository__free_extensions
(
void
);
#endif
tests/core/opts.c
View file @
4f24a932
#include "clar_libgit2.h"
#include "cache.h"
void
test_core_opts__cleanup
(
void
)
{
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_EXTENSIONS
,
NULL
,
0
));
}
void
test_core_opts__readwrite
(
void
)
{
size_t
old_val
=
0
;
...
...
@@ -23,3 +28,44 @@ void test_core_opts__invalid_option(void)
cl_git_fail
(
git_libgit2_opts
(
-
1
,
"foobar"
));
}
void
test_core_opts__extensions_query
(
void
)
{
git_strarray
out
=
{
0
};
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_GET_EXTENSIONS
,
&
out
));
cl_assert_equal_sz
(
out
.
count
,
1
);
cl_assert_equal_s
(
"noop"
,
out
.
strings
[
0
]);
git_strarray_dispose
(
&
out
);
}
void
test_core_opts__extensions_add
(
void
)
{
const
char
*
in
[]
=
{
"foo"
};
git_strarray
out
=
{
0
};
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_EXTENSIONS
,
in
,
ARRAY_SIZE
(
in
)));
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_GET_EXTENSIONS
,
&
out
));
cl_assert_equal_sz
(
out
.
count
,
2
);
cl_assert_equal_s
(
"noop"
,
out
.
strings
[
0
]);
cl_assert_equal_s
(
"foo"
,
out
.
strings
[
1
]);
git_strarray_dispose
(
&
out
);
}
void
test_core_opts__extensions_remove
(
void
)
{
const
char
*
in
[]
=
{
"bar"
,
"!negate"
,
"!noop"
,
"baz"
};
git_strarray
out
=
{
0
};
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_EXTENSIONS
,
in
,
ARRAY_SIZE
(
in
)));
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_GET_EXTENSIONS
,
&
out
));
cl_assert_equal_sz
(
out
.
count
,
2
);
cl_assert_equal_s
(
"bar"
,
out
.
strings
[
0
]);
cl_assert_equal_s
(
"baz"
,
out
.
strings
[
1
]);
git_strarray_dispose
(
&
out
);
}
tests/repo/extensions.c
0 → 100644
View file @
4f24a932
#include "clar_libgit2.h"
#include "futils.h"
#include "sysdir.h"
#include <ctype.h>
git_repository
*
repo
;
void
test_repo_extensions__initialize
(
void
)
{
git_config
*
config
;
repo
=
cl_git_sandbox_init
(
"empty_bare.git"
);
cl_git_pass
(
git_repository_config
(
&
config
,
repo
));
cl_git_pass
(
git_config_set_int32
(
config
,
"core.repositoryformatversion"
,
1
));
git_config_free
(
config
);
}
void
test_repo_extensions__cleanup
(
void
)
{
cl_git_sandbox_cleanup
();
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_EXTENSIONS
,
NULL
,
0
));
}
void
test_repo_extensions__builtin
(
void
)
{
git_repository
*
extended
;
cl_repo_set_string
(
repo
,
"extensions.noop"
,
"foobar"
);
cl_git_pass
(
git_repository_open
(
&
extended
,
"empty_bare.git"
));
cl_assert
(
git_repository_path
(
extended
)
!=
NULL
);
cl_assert
(
git__suffixcmp
(
git_repository_path
(
extended
),
"/"
)
==
0
);
git_repository_free
(
extended
);
}
void
test_repo_extensions__negate_builtin
(
void
)
{
const
char
*
in
[]
=
{
"foo"
,
"!noop"
,
"baz"
};
git_repository
*
extended
;
cl_repo_set_string
(
repo
,
"extensions.noop"
,
"foobar"
);
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_EXTENSIONS
,
in
,
ARRAY_SIZE
(
in
)));
cl_git_fail
(
git_repository_open
(
&
extended
,
"empty_bare.git"
));
git_repository_free
(
extended
);
}
void
test_repo_extensions__unsupported
(
void
)
{
git_repository
*
extended
=
NULL
;
cl_repo_set_string
(
repo
,
"extensions.unknown"
,
"foobar"
);
cl_git_fail
(
git_repository_open
(
&
extended
,
"empty_bare.git"
));
git_repository_free
(
extended
);
}
void
test_repo_extensions__adds_extension
(
void
)
{
const
char
*
in
[]
=
{
"foo"
,
"!noop"
,
"newextension"
,
"baz"
};
git_repository
*
extended
;
cl_repo_set_string
(
repo
,
"extensions.newextension"
,
"foobar"
);
cl_git_pass
(
git_libgit2_opts
(
GIT_OPT_SET_EXTENSIONS
,
in
,
ARRAY_SIZE
(
in
)));
cl_git_pass
(
git_repository_open
(
&
extended
,
"empty_bare.git"
));
cl_assert
(
git_repository_path
(
extended
)
!=
NULL
);
cl_assert
(
git__suffixcmp
(
git_repository_path
(
extended
),
"/"
)
==
0
);
git_repository_free
(
extended
);
}
tests/repo/open.c
View file @
4f24a932
...
...
@@ -42,48 +42,6 @@ void test_repo_open__format_version_1(void)
git_repository_free
(
repo
);
}
void
test_repo_open__format_version_1_with_valid_extension
(
void
)
{
git_repository
*
repo
;
git_config
*
config
;
repo
=
cl_git_sandbox_init
(
"empty_bare.git"
);
cl_git_pass
(
git_repository_open
(
&
repo
,
"empty_bare.git"
));
cl_git_pass
(
git_repository_config
(
&
config
,
repo
));
cl_git_pass
(
git_config_set_int32
(
config
,
"core.repositoryformatversion"
,
1
));
cl_git_pass
(
git_config_set_int32
(
config
,
"extensions.noop"
,
1
));
git_config_free
(
config
);
git_repository_free
(
repo
);
cl_git_pass
(
git_repository_open
(
&
repo
,
"empty_bare.git"
));
cl_assert
(
git_repository_path
(
repo
)
!=
NULL
);
cl_assert
(
git__suffixcmp
(
git_repository_path
(
repo
),
"/"
)
==
0
);
git_repository_free
(
repo
);
}
void
test_repo_open__format_version_1_with_invalid_extension
(
void
)
{
git_repository
*
repo
;
git_config
*
config
;
repo
=
cl_git_sandbox_init
(
"empty_bare.git"
);
cl_git_pass
(
git_repository_open
(
&
repo
,
"empty_bare.git"
));
cl_git_pass
(
git_repository_config
(
&
config
,
repo
));
cl_git_pass
(
git_config_set_int32
(
config
,
"core.repositoryformatversion"
,
1
));
cl_git_pass
(
git_config_set_int32
(
config
,
"extensions.invalid"
,
1
));
git_config_free
(
config
);
git_repository_free
(
repo
);
cl_git_fail
(
git_repository_open
(
&
repo
,
"empty_bare.git"
));
git_repository_free
(
repo
);
}
void
test_repo_open__standard_empty_repo_through_gitdir
(
void
)
{
git_repository
*
repo
;
...
...
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