Merge remote-tracking branch 'origin/main' into securetransport

This commit is contained in:
Edward Thomson
2024-09-26 16:48:35 +02:00
18 changed files with 311 additions and 113 deletions

View File

@@ -75,4 +75,5 @@ Tim Clem
Tim Harder
Torsten Bögershausen
Trent Mick
Venus Xeon-Blonde
Vicent Marti

View File

@@ -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;
/**

View File

@@ -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
*/

View File

@@ -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);

View File

@@ -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(&regex, entry->name) != 0)
if (regexp && git_regexp_match(&regex, 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)

View File

@@ -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(

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,

View 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);
}