mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-25 16:06:25 +00:00
Merge remote-tracking branch 'origin/main' into securetransport
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -75,4 +75,5 @@ Tim Clem
|
||||
Tim Harder
|
||||
Torsten Bögershausen
|
||||
Trent Mick
|
||||
Venus Xeon-Blonde
|
||||
Vicent Marti
|
||||
|
||||
@@ -97,12 +97,6 @@ typedef struct git_config_entry {
|
||||
|
||||
/** Configuration level for the file this was found in */
|
||||
git_config_level_t level;
|
||||
|
||||
/**
|
||||
* Free function for this entry; for internal purposes. Callers
|
||||
* should call `git_config_entry_free` to free data.
|
||||
*/
|
||||
void GIT_CALLBACK(free)(struct git_config_entry *entry);
|
||||
} git_config_entry;
|
||||
|
||||
/**
|
||||
|
||||
@@ -247,6 +247,9 @@ typedef int GIT_CALLBACK(git_packbuilder_progress)(
|
||||
* @param progress_cb Function to call with progress information during
|
||||
* pack building. Be aware that this is called inline with pack building
|
||||
* operations, so performance may be affected.
|
||||
* When progress_cb returns an error, the pack building process will be
|
||||
* aborted and the error will be returned from the invoked function.
|
||||
* `pb` must then be freed.
|
||||
* @param progress_cb_payload Payload for progress callback.
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,16 @@
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
typedef struct git_config_backend_entry {
|
||||
struct git_config_entry entry;
|
||||
|
||||
/**
|
||||
* Free function for this entry; for internal purposes. Callers
|
||||
* should call `git_config_entry_free` to free data.
|
||||
*/
|
||||
void GIT_CALLBACK(free)(struct git_config_backend_entry *entry);
|
||||
} git_config_backend_entry;
|
||||
|
||||
/**
|
||||
* Every iterator must have this struct as its first element, so the
|
||||
* API can talk to it. You'd define your iterator as
|
||||
@@ -39,7 +49,7 @@ struct git_config_iterator {
|
||||
* Return the current entry and advance the iterator. The
|
||||
* memory belongs to the library.
|
||||
*/
|
||||
int GIT_CALLBACK(next)(git_config_entry **entry, git_config_iterator *iter);
|
||||
int GIT_CALLBACK(next)(git_config_backend_entry **entry, git_config_iterator *iter);
|
||||
|
||||
/**
|
||||
* Free the iterator
|
||||
@@ -59,7 +69,7 @@ struct git_config_backend {
|
||||
|
||||
/* Open means open the file/database and parse if necessary */
|
||||
int GIT_CALLBACK(open)(struct git_config_backend *, git_config_level_t level, const git_repository *repo);
|
||||
int GIT_CALLBACK(get)(struct git_config_backend *, const char *key, git_config_entry **entry);
|
||||
int GIT_CALLBACK(get)(struct git_config_backend *, const char *key, git_config_backend_entry **entry);
|
||||
int GIT_CALLBACK(set)(struct git_config_backend *, const char *key, const char *value);
|
||||
int GIT_CALLBACK(set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
|
||||
int GIT_CALLBACK(del)(struct git_config_backend *, const char *key);
|
||||
|
||||
@@ -50,10 +50,13 @@ typedef struct {
|
||||
|
||||
void git_config_entry_free(git_config_entry *entry)
|
||||
{
|
||||
git_config_backend_entry *be;
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
entry->free(entry);
|
||||
be = (git_config_backend_entry *)entry;
|
||||
be->free(be);
|
||||
}
|
||||
|
||||
static void backend_instance_free(backend_instance *instance)
|
||||
@@ -430,15 +433,19 @@ typedef struct {
|
||||
size_t i;
|
||||
} all_iter;
|
||||
|
||||
static int all_iter_next(git_config_entry **out, git_config_iterator *_iter)
|
||||
static int all_iter_next(
|
||||
git_config_backend_entry **out,
|
||||
git_config_iterator *_iter)
|
||||
{
|
||||
all_iter *iter = (all_iter *) _iter;
|
||||
backend_entry *entry;
|
||||
git_config_backend *backend;
|
||||
git_config_backend_entry *be;
|
||||
int error = 0;
|
||||
|
||||
if (iter->current != NULL &&
|
||||
(error = iter->current->next(out, iter->current)) == 0) {
|
||||
(error = iter->current->next(&be, iter->current)) == 0) {
|
||||
*out = be;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -460,13 +467,18 @@ static int all_iter_next(git_config_entry **out, git_config_iterator *_iter)
|
||||
|
||||
iter->current = NULL;
|
||||
error = backend->iterator(&iter->current, backend);
|
||||
|
||||
if (error == GIT_ENOTFOUND)
|
||||
continue;
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = iter->current->next(out, iter->current);
|
||||
if ((error = iter->current->next(&be, iter->current)) == 0) {
|
||||
*out = be;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If this backend is empty, then keep going */
|
||||
if (error == GIT_ITEROVER)
|
||||
continue;
|
||||
@@ -478,7 +490,9 @@ static int all_iter_next(git_config_entry **out, git_config_iterator *_iter)
|
||||
return GIT_ITEROVER;
|
||||
}
|
||||
|
||||
static int all_iter_glob_next(git_config_entry **entry, git_config_iterator *_iter)
|
||||
static int all_iter_glob_next(
|
||||
git_config_backend_entry **entry,
|
||||
git_config_iterator *_iter)
|
||||
{
|
||||
int error;
|
||||
all_iter *iter = (all_iter *) _iter;
|
||||
@@ -489,7 +503,7 @@ static int all_iter_glob_next(git_config_entry **entry, git_config_iterator *_it
|
||||
*/
|
||||
while ((error = all_iter_next(entry, _iter)) == 0) {
|
||||
/* skip non-matching keys if regexp was provided */
|
||||
if (git_regexp_match(&iter->regex, (*entry)->name) != 0)
|
||||
if (git_regexp_match(&iter->regex, (*entry)->entry.name) != 0)
|
||||
continue;
|
||||
|
||||
/* and simply return if we like the entry's name */
|
||||
@@ -573,7 +587,7 @@ int git_config_backend_foreach_match(
|
||||
git_config_foreach_cb cb,
|
||||
void *payload)
|
||||
{
|
||||
git_config_entry *entry;
|
||||
git_config_backend_entry *entry;
|
||||
git_config_iterator *iter;
|
||||
git_regexp regex;
|
||||
int error = 0;
|
||||
@@ -591,11 +605,11 @@ int git_config_backend_foreach_match(
|
||||
|
||||
while (!(iter->next(&entry, iter) < 0)) {
|
||||
/* skip non-matching keys if regexp was provided */
|
||||
if (regexp && git_regexp_match(®ex, entry->name) != 0)
|
||||
if (regexp && git_regexp_match(®ex, entry->entry.name) != 0)
|
||||
continue;
|
||||
|
||||
/* abort iterator on non-zero return value */
|
||||
if ((error = cb(entry, payload)) != 0) {
|
||||
if ((error = cb(&entry->entry, payload)) != 0) {
|
||||
git_error_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
@@ -772,6 +786,7 @@ static int get_entry(
|
||||
{
|
||||
backend_entry *entry;
|
||||
git_config_backend *backend;
|
||||
git_config_backend_entry *be;
|
||||
int res = GIT_ENOTFOUND;
|
||||
const char *key = name;
|
||||
char *normalized = NULL;
|
||||
@@ -790,10 +805,12 @@ static int get_entry(
|
||||
GIT_ASSERT(entry->instance && entry->instance->backend);
|
||||
|
||||
backend = entry->instance->backend;
|
||||
res = backend->get(backend, key, out);
|
||||
res = backend->get(backend, key, &be);
|
||||
|
||||
if (res != GIT_ENOTFOUND)
|
||||
if (res != GIT_ENOTFOUND) {
|
||||
*out = &be->entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
git__free(normalized);
|
||||
@@ -1043,16 +1060,16 @@ int git_config_get_multivar_foreach(
|
||||
{
|
||||
int err, found;
|
||||
git_config_iterator *iter;
|
||||
git_config_entry *entry;
|
||||
git_config_backend_entry *be;
|
||||
|
||||
if ((err = git_config_multivar_iterator_new(&iter, config, name, regexp)) < 0)
|
||||
return err;
|
||||
|
||||
found = 0;
|
||||
while ((err = iter->next(&entry, iter)) == 0) {
|
||||
while ((err = iter->next(&be, iter)) == 0) {
|
||||
found = 1;
|
||||
|
||||
if ((err = cb(entry, payload)) != 0) {
|
||||
if ((err = cb(&be->entry, payload)) != 0) {
|
||||
git_error_set_after_callback(err);
|
||||
break;
|
||||
}
|
||||
@@ -1076,19 +1093,21 @@ typedef struct {
|
||||
int have_regex;
|
||||
} multivar_iter;
|
||||
|
||||
static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_iter)
|
||||
static int multivar_iter_next(
|
||||
git_config_backend_entry **entry,
|
||||
git_config_iterator *_iter)
|
||||
{
|
||||
multivar_iter *iter = (multivar_iter *) _iter;
|
||||
int error = 0;
|
||||
|
||||
while ((error = iter->iter->next(entry, iter->iter)) == 0) {
|
||||
if (git__strcmp(iter->name, (*entry)->name))
|
||||
if (git__strcmp(iter->name, (*entry)->entry.name))
|
||||
continue;
|
||||
|
||||
if (!iter->have_regex)
|
||||
return 0;
|
||||
|
||||
if (git_regexp_match(&iter->regex, (*entry)->value) == 0)
|
||||
if (git_regexp_match(&iter->regex, (*entry)->entry.value) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1168,7 +1187,14 @@ int git_config_delete_multivar(git_config *config, const char *name, const char
|
||||
|
||||
int git_config_next(git_config_entry **entry, git_config_iterator *iter)
|
||||
{
|
||||
return iter->next(entry, iter);
|
||||
git_config_backend_entry *be;
|
||||
int error;
|
||||
|
||||
if ((error = iter->next(&be, iter)) != 0)
|
||||
return error;
|
||||
|
||||
*entry = &be->entry;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_config_iterator_free(git_config_iterator *iter)
|
||||
|
||||
@@ -51,7 +51,14 @@ GIT_INLINE(void) git_config_backend_free(git_config_backend *cfg)
|
||||
GIT_INLINE(int) git_config_backend_get_string(
|
||||
git_config_entry **out, git_config_backend *cfg, const char *name)
|
||||
{
|
||||
return cfg->get(cfg, name, out);
|
||||
git_config_backend_entry *be;
|
||||
int error;
|
||||
|
||||
if ((error = cfg->get(cfg, name, &be)) < 0)
|
||||
return error;
|
||||
|
||||
*out = &be->entry;
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_config_backend_set_string(
|
||||
|
||||
@@ -310,8 +310,8 @@ static int config_file_set(git_config_backend *cfg, const char *name, const char
|
||||
if (error != GIT_ENOTFOUND)
|
||||
goto out;
|
||||
error = 0;
|
||||
} else if ((!existing->base.value && !value) ||
|
||||
(existing->base.value && value && !strcmp(existing->base.value, value))) {
|
||||
} else if ((!existing->base.entry.value && !value) ||
|
||||
(existing->base.entry.value && value && !strcmp(existing->base.entry.value, value))) {
|
||||
/* don't update if old and new values already match */
|
||||
error = 0;
|
||||
goto out;
|
||||
@@ -336,7 +336,10 @@ out:
|
||||
/*
|
||||
* Internal function that actually gets the value in string form
|
||||
*/
|
||||
static int config_file_get(git_config_backend *cfg, const char *key, git_config_entry **out)
|
||||
static int config_file_get(
|
||||
git_config_backend *cfg,
|
||||
const char *key,
|
||||
git_config_backend_entry **out)
|
||||
{
|
||||
config_file_backend *h = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
|
||||
git_config_list *config_list = NULL;
|
||||
@@ -407,7 +410,7 @@ static int config_file_delete(git_config_backend *cfg, const char *name)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((error = config_file_write(b, name, entry->base.name, NULL, NULL)) < 0)
|
||||
if ((error = config_file_write(b, name, entry->base.entry.name, NULL, NULL)) < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
@@ -795,22 +798,22 @@ static int read_on_variable(
|
||||
entry = git__calloc(1, sizeof(git_config_list_entry));
|
||||
GIT_ERROR_CHECK_ALLOC(entry);
|
||||
|
||||
entry->base.name = git_str_detach(&buf);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.name);
|
||||
entry->base.entry.name = git_str_detach(&buf);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.entry.name);
|
||||
|
||||
if (var_value) {
|
||||
entry->base.value = git__strdup(var_value);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.value);
|
||||
entry->base.entry.value = git__strdup(var_value);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.entry.value);
|
||||
}
|
||||
|
||||
entry->base.backend_type = git_config_list_add_string(parse_data->config_list, CONFIG_FILE_TYPE);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.backend_type);
|
||||
entry->base.entry.backend_type = git_config_list_add_string(parse_data->config_list, CONFIG_FILE_TYPE);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.entry.backend_type);
|
||||
|
||||
entry->base.origin_path = git_config_list_add_string(parse_data->config_list, parse_data->file->path);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.origin_path);
|
||||
entry->base.entry.origin_path = git_config_list_add_string(parse_data->config_list, parse_data->file->path);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.entry.origin_path);
|
||||
|
||||
entry->base.level = parse_data->level;
|
||||
entry->base.include_depth = parse_data->depth;
|
||||
entry->base.entry.level = parse_data->level;
|
||||
entry->base.entry.include_depth = parse_data->depth;
|
||||
entry->base.free = git_config_list_entry_free;
|
||||
entry->config_list = parse_data->config_list;
|
||||
|
||||
@@ -820,11 +823,11 @@ static int read_on_variable(
|
||||
result = 0;
|
||||
|
||||
/* Add or append the new config option */
|
||||
if (!git__strcmp(entry->base.name, "include.path"))
|
||||
result = parse_include(parse_data, entry->base.value);
|
||||
else if (!git__prefixcmp(entry->base.name, "includeif.") &&
|
||||
!git__suffixcmp(entry->base.name, ".path"))
|
||||
result = parse_conditional_include(parse_data, entry->base.name, entry->base.value);
|
||||
if (!git__strcmp(entry->base.entry.name, "include.path"))
|
||||
result = parse_include(parse_data, entry->base.entry.value);
|
||||
else if (!git__prefixcmp(entry->base.entry.name, "includeif.") &&
|
||||
!git__suffixcmp(entry->base.entry.name, ".path"))
|
||||
result = parse_conditional_include(parse_data, entry->base.entry.name, entry->base.entry.value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -64,24 +64,24 @@ int git_config_list_dup_entry(git_config_list *config_list, const git_config_ent
|
||||
duplicated = git__calloc(1, sizeof(git_config_list_entry));
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated);
|
||||
|
||||
duplicated->base.name = git__strdup(entry->name);
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated->base.name);
|
||||
duplicated->base.entry.name = git__strdup(entry->name);
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated->base.entry.name);
|
||||
|
||||
if (entry->value) {
|
||||
duplicated->base.value = git__strdup(entry->value);
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated->base.value);
|
||||
duplicated->base.entry.value = git__strdup(entry->value);
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated->base.entry.value);
|
||||
}
|
||||
|
||||
duplicated->base.backend_type = git_config_list_add_string(config_list, entry->backend_type);
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated->base.backend_type);
|
||||
duplicated->base.entry.backend_type = git_config_list_add_string(config_list, entry->backend_type);
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated->base.entry.backend_type);
|
||||
|
||||
if (entry->origin_path) {
|
||||
duplicated->base.origin_path = git_config_list_add_string(config_list, entry->origin_path);
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated->base.origin_path);
|
||||
duplicated->base.entry.origin_path = git_config_list_add_string(config_list, entry->origin_path);
|
||||
GIT_ERROR_CHECK_ALLOC(duplicated->base.entry.origin_path);
|
||||
}
|
||||
|
||||
duplicated->base.level = entry->level;
|
||||
duplicated->base.include_depth = entry->include_depth;
|
||||
duplicated->base.entry.level = entry->level;
|
||||
duplicated->base.entry.include_depth = entry->include_depth;
|
||||
duplicated->base.free = git_config_list_entry_free;
|
||||
duplicated->config_list = config_list;
|
||||
|
||||
@@ -90,8 +90,8 @@ int git_config_list_dup_entry(git_config_list *config_list, const git_config_ent
|
||||
|
||||
out:
|
||||
if (error && duplicated) {
|
||||
git__free((char *) duplicated->base.name);
|
||||
git__free((char *) duplicated->base.value);
|
||||
git__free((char *) duplicated->base.entry.name);
|
||||
git__free((char *) duplicated->base.entry.value);
|
||||
git__free(duplicated);
|
||||
}
|
||||
return error;
|
||||
@@ -107,7 +107,7 @@ int git_config_list_dup(git_config_list **out, git_config_list *config_list)
|
||||
goto out;
|
||||
|
||||
for (head = config_list->entries; head; head = head->next)
|
||||
if ((git_config_list_dup_entry(result, &head->entry->base)) < 0)
|
||||
if ((git_config_list_dup_entry(result, &head->entry->base.entry)) < 0)
|
||||
goto out;
|
||||
|
||||
*out = result;
|
||||
@@ -135,7 +135,7 @@ static void config_list_free(git_config_list *config_list)
|
||||
git_strmap_free(config_list->strings);
|
||||
|
||||
git_strmap_foreach_value(config_list->map, head, {
|
||||
git__free((char *) head->entry->base.name);
|
||||
git__free((char *) head->entry->base.entry.name);
|
||||
git__free(head);
|
||||
});
|
||||
git_strmap_free(config_list->map);
|
||||
@@ -143,7 +143,7 @@ static void config_list_free(git_config_list *config_list)
|
||||
entry_list = config_list->entries;
|
||||
while (entry_list != NULL) {
|
||||
next = entry_list->next;
|
||||
git__free((char *) entry_list->entry->base.value);
|
||||
git__free((char *) entry_list->entry->base.entry.value);
|
||||
git__free(entry_list->entry);
|
||||
git__free(entry_list);
|
||||
entry_list = next;
|
||||
@@ -163,7 +163,7 @@ int git_config_list_append(git_config_list *config_list, git_config_list_entry *
|
||||
config_entry_list *list_head;
|
||||
config_entry_map_head *map_head;
|
||||
|
||||
if ((map_head = git_strmap_get(config_list->map, entry->base.name)) != NULL) {
|
||||
if ((map_head = git_strmap_get(config_list->map, entry->base.entry.name)) != NULL) {
|
||||
map_head->multivar = true;
|
||||
/*
|
||||
* This is a micro-optimization for configuration files
|
||||
@@ -171,11 +171,11 @@ int git_config_list_append(git_config_list *config_list, git_config_list_entry *
|
||||
* key will be the same for all list, we can just free
|
||||
* all except the first entry's name and just re-use it.
|
||||
*/
|
||||
git__free((char *) entry->base.name);
|
||||
entry->base.name = map_head->entry->base.name;
|
||||
git__free((char *) entry->base.entry.name);
|
||||
entry->base.entry.name = map_head->entry->base.entry.name;
|
||||
} else {
|
||||
map_head = git__calloc(1, sizeof(*map_head));
|
||||
if ((git_strmap_set(config_list->map, entry->base.name, map_head)) < 0)
|
||||
if ((git_strmap_set(config_list->map, entry->base.entry.name, map_head)) < 0)
|
||||
return -1;
|
||||
}
|
||||
map_head->entry = entry;
|
||||
@@ -216,7 +216,7 @@ int git_config_list_get_unique(git_config_list_entry **out, git_config_list *con
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (entry->entry->base.include_depth) {
|
||||
if (entry->entry->base.entry.include_depth) {
|
||||
git_error_set(GIT_ERROR_CONFIG, "entry is not unique due to being included");
|
||||
return -1;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ static void config_iterator_free(git_config_iterator *iter)
|
||||
}
|
||||
|
||||
static int config_iterator_next(
|
||||
git_config_entry **entry,
|
||||
git_config_backend_entry **entry,
|
||||
git_config_iterator *iter)
|
||||
{
|
||||
config_list_iterator *it = (config_list_iterator *) iter;
|
||||
@@ -265,7 +265,7 @@ int git_config_list_iterator_new(git_config_iterator **out, git_config_list *con
|
||||
}
|
||||
|
||||
/* release the map containing the entry as an equivalent to freeing it */
|
||||
void git_config_list_entry_free(git_config_entry *e)
|
||||
void git_config_list_entry_free(git_config_backend_entry *e)
|
||||
{
|
||||
git_config_list_entry *entry = (git_config_list_entry *)e;
|
||||
git_config_list_free(entry->config_list);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
typedef struct git_config_list git_config_list;
|
||||
|
||||
typedef struct {
|
||||
git_config_entry base;
|
||||
git_config_backend_entry base;
|
||||
git_config_list *config_list;
|
||||
} git_config_list_entry;
|
||||
|
||||
@@ -29,4 +29,4 @@ int git_config_list_get_unique(git_config_list_entry **out, git_config_list *lis
|
||||
int git_config_list_iterator_new(git_config_iterator **out, git_config_list *list);
|
||||
const char *git_config_list_add_string(git_config_list *list, const char *str);
|
||||
|
||||
void git_config_list_entry_free(git_config_entry *entry);
|
||||
void git_config_list_entry_free(git_config_backend_entry *entry);
|
||||
|
||||
@@ -77,12 +77,12 @@ static int read_variable_cb(
|
||||
|
||||
entry = git__calloc(1, sizeof(git_config_list_entry));
|
||||
GIT_ERROR_CHECK_ALLOC(entry);
|
||||
entry->base.name = git_str_detach(&buf);
|
||||
entry->base.value = var_value ? git__strdup(var_value) : NULL;
|
||||
entry->base.level = parse_data->level;
|
||||
entry->base.include_depth = 0;
|
||||
entry->base.backend_type = parse_data->backend_type;
|
||||
entry->base.origin_path = parse_data->origin_path;
|
||||
entry->base.entry.name = git_str_detach(&buf);
|
||||
entry->base.entry.value = var_value ? git__strdup(var_value) : NULL;
|
||||
entry->base.entry.level = parse_data->level;
|
||||
entry->base.entry.include_depth = 0;
|
||||
entry->base.entry.backend_type = parse_data->backend_type;
|
||||
entry->base.entry.origin_path = parse_data->origin_path;
|
||||
entry->base.free = git_config_list_entry_free;
|
||||
entry->config_list = parse_data->config_list;
|
||||
|
||||
@@ -151,18 +151,18 @@ static int parse_values(
|
||||
entry = git__calloc(1, sizeof(git_config_list_entry));
|
||||
GIT_ERROR_CHECK_ALLOC(entry);
|
||||
|
||||
entry->base.name = git__strndup(memory_backend->values[i], name_len);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.name);
|
||||
entry->base.entry.name = git__strndup(memory_backend->values[i], name_len);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.entry.name);
|
||||
|
||||
if (eql) {
|
||||
entry->base.value = git__strdup(eql + 1);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.value);
|
||||
entry->base.entry.value = git__strdup(eql + 1);
|
||||
GIT_ERROR_CHECK_ALLOC(entry->base.entry.value);
|
||||
}
|
||||
|
||||
entry->base.level = level;
|
||||
entry->base.include_depth = 0;
|
||||
entry->base.backend_type = backend_type;
|
||||
entry->base.origin_path = origin_path;
|
||||
entry->base.entry.level = level;
|
||||
entry->base.entry.include_depth = 0;
|
||||
entry->base.entry.backend_type = backend_type;
|
||||
entry->base.entry.origin_path = origin_path;
|
||||
entry->base.free = git_config_list_entry_free;
|
||||
entry->config_list = memory_backend->config_list;
|
||||
|
||||
@@ -190,7 +190,7 @@ static int config_memory_open(git_config_backend *backend, git_config_level_t le
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_memory_get(git_config_backend *backend, const char *key, git_config_entry **out)
|
||||
static int config_memory_get(git_config_backend *backend, const char *key, git_config_backend_entry **out)
|
||||
{
|
||||
config_memory_backend *memory_backend = (config_memory_backend *) backend;
|
||||
git_config_list_entry *entry;
|
||||
|
||||
@@ -41,7 +41,10 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int config_snapshot_get(git_config_backend *cfg, const char *key, git_config_entry **out)
|
||||
static int config_snapshot_get(
|
||||
git_config_backend *cfg,
|
||||
const char *key,
|
||||
git_config_backend_entry **out)
|
||||
{
|
||||
config_snapshot_backend *b = GIT_CONTAINER_OF(cfg, config_snapshot_backend, parent);
|
||||
git_config_list *config_list = NULL;
|
||||
|
||||
@@ -667,6 +667,13 @@ static int diff_print_patch_binary(
|
||||
if ((error = flush_file_header(delta, pi)) < 0)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* If the caller only wants the header, we just needed to make sure to
|
||||
* call flush_file_header
|
||||
*/
|
||||
if (pi->format == GIT_DIFF_FORMAT_PATCH_HEADER)
|
||||
return 0;
|
||||
|
||||
git_str_clear(pi->buf);
|
||||
|
||||
if ((error = diff_print_patch_file_binary(
|
||||
@@ -694,6 +701,13 @@ static int diff_print_patch_hunk(
|
||||
if ((error = flush_file_header(d, pi)) < 0)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* If the caller only wants the header, we just needed to make sure to
|
||||
* call flush_file_header
|
||||
*/
|
||||
if (pi->format == GIT_DIFF_FORMAT_PATCH_HEADER)
|
||||
return 0;
|
||||
|
||||
pi->line.origin = GIT_DIFF_LINE_HUNK_HDR;
|
||||
pi->line.content = h->header;
|
||||
pi->line.content_len = h->header_len;
|
||||
@@ -748,6 +762,8 @@ int git_diff_print(
|
||||
break;
|
||||
case GIT_DIFF_FORMAT_PATCH_HEADER:
|
||||
print_file = diff_print_patch_file;
|
||||
print_binary = diff_print_patch_binary;
|
||||
print_hunk = diff_print_patch_hunk;
|
||||
break;
|
||||
case GIT_DIFF_FORMAT_RAW:
|
||||
print_file = diff_print_one_raw;
|
||||
|
||||
@@ -786,8 +786,10 @@ static int truncate_racily_clean(git_index *index)
|
||||
diff_opts.pathspec.count = paths.length;
|
||||
diff_opts.pathspec.strings = (char **)paths.contents;
|
||||
|
||||
if ((error = git_diff_index_to_workdir(&diff, INDEX_OWNER(index), index, &diff_opts)) < 0)
|
||||
return error;
|
||||
if ((error = git_diff_index_to_workdir(&diff, INDEX_OWNER(index), index, &diff_opts)) < 0) {
|
||||
git_vector_free(&paths);
|
||||
return error;
|
||||
}
|
||||
|
||||
git_vector_foreach(&diff->deltas, i, delta) {
|
||||
entry = (git_index_entry *)git_index_get_bypath(index, delta->old_file.path, 0);
|
||||
|
||||
@@ -932,6 +932,9 @@ static int report_delta_progress(
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (pb->failure)
|
||||
return pb->failure;
|
||||
|
||||
if (pb->progress_cb) {
|
||||
uint64_t current_time = git_time_monotonic();
|
||||
uint64_t elapsed = current_time - pb->last_progress_report_time;
|
||||
@@ -943,8 +946,10 @@ static int report_delta_progress(
|
||||
GIT_PACKBUILDER_DELTAFICATION,
|
||||
count, pb->nr_objects, pb->progress_cb_payload);
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
pb->failure = ret;
|
||||
return git_error_set_after_callback(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -976,7 +981,10 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list,
|
||||
}
|
||||
|
||||
pb->nr_deltified += 1;
|
||||
report_delta_progress(pb, pb->nr_deltified, false);
|
||||
if ((error = report_delta_progress(pb, pb->nr_deltified, false)) < 0) {
|
||||
GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
po = *list++;
|
||||
(*list_size)--;
|
||||
@@ -1124,6 +1132,10 @@ struct thread_params {
|
||||
size_t depth;
|
||||
size_t working;
|
||||
size_t data_ready;
|
||||
|
||||
/* A pb->progress_cb can stop the packing process by returning an error.
|
||||
When that happens, all threads observe the error and stop voluntarily. */
|
||||
bool stopped;
|
||||
};
|
||||
|
||||
static void *threaded_find_deltas(void *arg)
|
||||
@@ -1133,7 +1145,12 @@ static void *threaded_find_deltas(void *arg)
|
||||
while (me->remaining) {
|
||||
if (find_deltas(me->pb, me->list, &me->remaining,
|
||||
me->window, me->depth) < 0) {
|
||||
; /* TODO */
|
||||
me->stopped = true;
|
||||
GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_lock(me->pb) == 0, NULL);
|
||||
me->working = false;
|
||||
git_cond_signal(&me->pb->progress_cond);
|
||||
GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_unlock(me->pb) == 0, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GIT_ASSERT_WITH_RETVAL(git_packbuilder__progress_lock(me->pb) == 0, NULL);
|
||||
@@ -1175,8 +1192,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
|
||||
pb->nr_threads = git__online_cpus();
|
||||
|
||||
if (pb->nr_threads <= 1) {
|
||||
find_deltas(pb, list, &list_size, window, depth);
|
||||
return 0;
|
||||
return find_deltas(pb, list, &list_size, window, depth);
|
||||
}
|
||||
|
||||
p = git__mallocarray(pb->nr_threads, sizeof(*p));
|
||||
@@ -1195,6 +1211,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
|
||||
p[i].depth = depth;
|
||||
p[i].working = 1;
|
||||
p[i].data_ready = 0;
|
||||
p[i].stopped = 0;
|
||||
|
||||
/* try to split chunks on "path" boundaries */
|
||||
while (sub_size && sub_size < list_size &&
|
||||
@@ -1262,7 +1279,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
|
||||
(!victim || victim->remaining < p[i].remaining))
|
||||
victim = &p[i];
|
||||
|
||||
if (victim) {
|
||||
if (victim && !target->stopped) {
|
||||
sub_size = victim->remaining / 2;
|
||||
list = victim->list + victim->list_size - sub_size;
|
||||
while (sub_size && list[0]->hash &&
|
||||
@@ -1286,7 +1303,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
|
||||
}
|
||||
target->list_size = sub_size;
|
||||
target->remaining = sub_size;
|
||||
target->working = 1;
|
||||
target->working = 1; /* even when target->stopped, so that we don't process this thread again */
|
||||
GIT_ASSERT(git_packbuilder__progress_unlock(pb) == 0);
|
||||
|
||||
if (git_mutex_lock(&target->mutex)) {
|
||||
@@ -1299,7 +1316,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
|
||||
git_cond_signal(&target->cond);
|
||||
git_mutex_unlock(&target->mutex);
|
||||
|
||||
if (!sub_size) {
|
||||
if (target->stopped || !sub_size) {
|
||||
git_thread_join(&target->thread, NULL);
|
||||
git_cond_free(&target->cond);
|
||||
git_mutex_free(&target->mutex);
|
||||
@@ -1308,7 +1325,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
|
||||
}
|
||||
|
||||
git__free(p);
|
||||
return 0;
|
||||
return pb->failure;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -1319,6 +1336,7 @@ int git_packbuilder__prepare(git_packbuilder *pb)
|
||||
{
|
||||
git_pobject **delta_list;
|
||||
size_t i, n = 0;
|
||||
int error;
|
||||
|
||||
if (pb->nr_objects == 0 || pb->done)
|
||||
return 0; /* nothing to do */
|
||||
@@ -1327,8 +1345,10 @@ int git_packbuilder__prepare(git_packbuilder *pb)
|
||||
* Although we do not report progress during deltafication, we
|
||||
* at least report that we are in the deltafication stage
|
||||
*/
|
||||
if (pb->progress_cb)
|
||||
pb->progress_cb(GIT_PACKBUILDER_DELTAFICATION, 0, pb->nr_objects, pb->progress_cb_payload);
|
||||
if (pb->progress_cb) {
|
||||
if ((error = pb->progress_cb(GIT_PACKBUILDER_DELTAFICATION, 0, pb->nr_objects, pb->progress_cb_payload)) < 0)
|
||||
return git_error_set_after_callback(error);
|
||||
}
|
||||
|
||||
delta_list = git__mallocarray(pb->nr_objects, sizeof(*delta_list));
|
||||
GIT_ERROR_CHECK_ALLOC(delta_list);
|
||||
@@ -1345,31 +1365,33 @@ int git_packbuilder__prepare(git_packbuilder *pb)
|
||||
|
||||
if (n > 1) {
|
||||
git__tsort((void **)delta_list, n, type_size_sort);
|
||||
if (ll_find_deltas(pb, delta_list, n,
|
||||
if ((error = ll_find_deltas(pb, delta_list, n,
|
||||
GIT_PACK_WINDOW + 1,
|
||||
GIT_PACK_DEPTH) < 0) {
|
||||
GIT_PACK_DEPTH)) < 0) {
|
||||
git__free(delta_list);
|
||||
return -1;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
report_delta_progress(pb, pb->nr_objects, true);
|
||||
error = report_delta_progress(pb, pb->nr_objects, true);
|
||||
|
||||
pb->done = true;
|
||||
git__free(delta_list);
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
#define PREPARE_PACK if (git_packbuilder__prepare(pb) < 0) { return -1; }
|
||||
#define PREPARE_PACK error = git_packbuilder__prepare(pb); if (error < 0) { return error; }
|
||||
|
||||
int git_packbuilder_foreach(git_packbuilder *pb, int (*cb)(void *buf, size_t size, void *payload), void *payload)
|
||||
{
|
||||
int error;
|
||||
PREPARE_PACK;
|
||||
return write_pack(pb, cb, payload);
|
||||
}
|
||||
|
||||
int git_packbuilder__write_buf(git_str *buf, git_packbuilder *pb)
|
||||
{
|
||||
int error;
|
||||
PREPARE_PACK;
|
||||
|
||||
return write_pack(pb, &write_pack_buf, buf);
|
||||
|
||||
@@ -100,6 +100,10 @@ struct git_packbuilder {
|
||||
uint64_t last_progress_report_time;
|
||||
|
||||
bool done;
|
||||
|
||||
/* A non-zero error code in failure causes all threads to shut themselves
|
||||
down. Some functions will return this error code. */
|
||||
volatile int failure;
|
||||
};
|
||||
|
||||
int git_packbuilder__write_buf(git_str *buf, git_packbuilder *pb);
|
||||
|
||||
@@ -13,24 +13,57 @@
|
||||
#include <Security/SecureTransport.h>
|
||||
#include <Security/SecCertificate.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "trace.h"
|
||||
#include "git2/transport.h"
|
||||
|
||||
#include "streams/socket.h"
|
||||
|
||||
static int stransport_error(OSStatus ret)
|
||||
{
|
||||
CFStringRef message;
|
||||
CFStringRef message_ref;
|
||||
const char *message_cstr;
|
||||
char *message_ptr = NULL;
|
||||
|
||||
if (ret == noErr || ret == errSSLClosedGraceful) {
|
||||
git_error_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
message = SecCopyErrorMessageString(ret, NULL);
|
||||
GIT_ERROR_CHECK_ALLOC(message);
|
||||
#if !TARGET_OS_IPHONE
|
||||
message_ref = SecCopyErrorMessageString(ret, NULL);
|
||||
GIT_ERROR_CHECK_ALLOC(message_ref);
|
||||
|
||||
git_error_set(GIT_ERROR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8));
|
||||
CFRelease(message);
|
||||
/*
|
||||
* Attempt the cheap CFString conversion; this can return NULL
|
||||
* when that would be expensive. In that case, call the more
|
||||
* expensive function.
|
||||
*/
|
||||
message_cstr = CFStringGetCStringPtr(message_ref, kCFStringEncodingUTF8);
|
||||
|
||||
if (!message_cstr) {
|
||||
/* Provide buffer to convert from UTF16 to UTF8 */
|
||||
size_t message_size = CFStringGetLength(message_ref) * 2 + 1;
|
||||
|
||||
message_cstr = message_ptr = git__malloc(message_size);
|
||||
GIT_ERROR_CHECK_ALLOC(message_ptr);
|
||||
|
||||
if (!CFStringGetCString(message_ref, message_ptr, message_size, kCFStringEncodingUTF8)) {
|
||||
git_error_set(GIT_ERROR_NET, "SecureTransport error: %d", (unsigned int)ret);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
git_error_set(GIT_ERROR_NET, "SecureTransport error: %s", message_cstr);
|
||||
|
||||
done:
|
||||
git__free(message_ptr);
|
||||
CFRelease(message_ref);
|
||||
#else
|
||||
git_error_set(GIT_ERROR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
|
||||
GIT_UNUSED(message);
|
||||
GIT_UNUSED(message_cstr);
|
||||
GIT_UNUSED(must_free);
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -231,6 +264,10 @@ static ssize_t stransport_read(git_stream *stream, void *data, size_t len)
|
||||
OSStatus ret;
|
||||
|
||||
if ((ret = SSLRead(st->ctx, data, len, &processed)) != noErr) {
|
||||
/* This specific SecureTransport error is not well described */
|
||||
if (ret == -9806)
|
||||
git_trace(GIT_TRACE_INFO, "SecureTraceport error during SSLRead: returned -9806 (connection closed via error)");
|
||||
|
||||
if (st->error == GIT_TIMEOUT)
|
||||
return GIT_TIMEOUT;
|
||||
|
||||
|
||||
@@ -158,9 +158,10 @@ static int get_ssh_cmdline(
|
||||
else if ((error = git_config__get_string_buf(&ssh_cmd, cfg, "core.sshcommand")) < 0 && error != GIT_ENOTFOUND)
|
||||
goto done;
|
||||
|
||||
error = git_str_printf(out, "%s -p %s \"%s%s%s\" \"%s\" \"%s\"",
|
||||
error = git_str_printf(out, "%s %s %s \"%s%s%s\" \"%s\" \"%s\"",
|
||||
ssh_cmd.size > 0 ? ssh_cmd.ptr : default_ssh_cmd,
|
||||
url->port,
|
||||
url->port_specified ? "-p" : "",
|
||||
url->port_specified ? url->port : "",
|
||||
url->username ? url->username : "",
|
||||
url->username ? "@" : "",
|
||||
url->host,
|
||||
|
||||
69
tests/libgit2/diff/header.c
Normal file
69
tests/libgit2/diff/header.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/sys/repository.h"
|
||||
|
||||
#include "diff_helpers.h"
|
||||
#include "diff.h"
|
||||
#include "repository.h"
|
||||
|
||||
static git_repository *g_repo = NULL;
|
||||
|
||||
void test_diff_header__initialize(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_diff_header__cleanup(void)
|
||||
{
|
||||
cl_git_sandbox_cleanup();
|
||||
}
|
||||
|
||||
#define EXPECTED_HEADER "diff --git a/subdir.txt b/subdir.txt\n" \
|
||||
"deleted file mode 100644\n" \
|
||||
"index e8ee89e..0000000\n" \
|
||||
"--- a/subdir.txt\n" \
|
||||
"+++ /dev/null\n"
|
||||
|
||||
static int check_header_cb(
|
||||
const git_diff_delta *delta,
|
||||
const git_diff_hunk *hunk,
|
||||
const git_diff_line *line,
|
||||
void *payload)
|
||||
{
|
||||
int *counter = (int *) payload;
|
||||
|
||||
GIT_UNUSED(delta);
|
||||
|
||||
switch (line->origin) {
|
||||
case GIT_DIFF_LINE_FILE_HDR:
|
||||
cl_assert(hunk == NULL);
|
||||
(*counter)++;
|
||||
break;
|
||||
default:
|
||||
/* unexpected code path */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_diff_header__can_print_just_headers(void)
|
||||
{
|
||||
const char *one_sha = "26a125e";
|
||||
git_tree *one;
|
||||
git_diff *diff;
|
||||
int counter = 0;
|
||||
|
||||
g_repo = cl_git_sandbox_init("status");
|
||||
|
||||
one = resolve_commit_oid_to_tree(g_repo, one_sha);
|
||||
|
||||
cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, NULL));
|
||||
|
||||
cl_git_pass(git_diff_print(
|
||||
diff, GIT_DIFF_FORMAT_PATCH_HEADER, check_header_cb, &counter));
|
||||
|
||||
cl_assert_equal_i(8, counter);
|
||||
|
||||
git_diff_free(diff);
|
||||
|
||||
git_tree_free(one);
|
||||
}
|
||||
Reference in New Issue
Block a user