mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-02 12:29:08 +00:00
Merge remote-tracking branch 'arrbee/tree-walk-fixes' into development
Conflicts: src/notes.c src/transports/git.c src/transports/http.c src/transports/local.c tests-clar/odb/foreach.c
This commit is contained in:
commit
51e1d80846
@ -188,18 +188,17 @@ GIT_EXTERN(int) git_attr_get_many(
|
||||
*
|
||||
* @param repo The repository containing the path.
|
||||
* @param flags A combination of GIT_ATTR_CHECK... flags.
|
||||
* @param path The path inside the repo to check attributes. This
|
||||
* does not have to exist, but if it does not, then
|
||||
* it will be treated as a plain file (i.e. not a directory).
|
||||
* @param callback The function that will be invoked on each attribute
|
||||
* and attribute value. The name parameter will be the name
|
||||
* of the attribute and the value will be the value it is
|
||||
* set to, including possibly NULL if the attribute is
|
||||
* explicitly set to UNSPECIFIED using the ! sign. This
|
||||
* will be invoked only once per attribute name, even if
|
||||
* there are multiple rules for a given file. The highest
|
||||
* priority rule will be used.
|
||||
* @param path Path inside the repo to check attributes. This does not have
|
||||
* to exist, but if it does not, then it will be treated as a
|
||||
* plain file (i.e. not a directory).
|
||||
* @param callback Function to invoke on each attribute name and value. The
|
||||
* value may be NULL is the attribute is explicitly set to
|
||||
* UNSPECIFIED using the '!' sign. Callback will be invoked
|
||||
* only once per attribute name, even if there are multiple
|
||||
* rules for a given file. The highest priority rule will be
|
||||
* used. Return a non-zero value from this to stop looping.
|
||||
* @param payload Passed on as extra parameter to callback function.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_attr_foreach(
|
||||
git_repository *repo,
|
||||
|
@ -74,6 +74,8 @@ GIT_EXTERN(int) git_branch_delete(
|
||||
/**
|
||||
* Loop over all the branches and issue a callback for each one.
|
||||
*
|
||||
* If the callback returns a non-zero value, this will stop looping.
|
||||
*
|
||||
* @param repo Repository where to find the branches.
|
||||
*
|
||||
* @param list_flags Filtering flags for the branch
|
||||
@ -84,7 +86,7 @@ GIT_EXTERN(int) git_branch_delete(
|
||||
*
|
||||
* @param payload Extra parameter to callback function.
|
||||
*
|
||||
* @return 0 or an error code.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_branch_foreach(
|
||||
git_repository *repo,
|
||||
|
@ -302,12 +302,12 @@ GIT_EXTERN(int) git_config_delete(git_config *cfg, const char *name);
|
||||
* The callback receives the normalized name and value of each variable
|
||||
* in the config backend, and the data pointer passed to this function.
|
||||
* As soon as one of the callback functions returns something other than 0,
|
||||
* this function returns that value.
|
||||
* this function stops iterating and returns `GIT_EUSER`.
|
||||
*
|
||||
* @param cfg where to get the variables from
|
||||
* @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
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_foreach(
|
||||
git_config *cfg,
|
||||
|
@ -332,6 +332,9 @@ GIT_EXTERN(int) git_diff_merge(
|
||||
* callbacks will not be invoked for binary files on the diff list or for
|
||||
* files whose only changed is a file mode change.
|
||||
*
|
||||
* Returning a non-zero value from any of the callbacks will terminate
|
||||
* the iteration and cause this return `GIT_EUSER`.
|
||||
*
|
||||
* @param diff A git_diff_list generated by one of the above functions.
|
||||
* @param cb_data Reference pointer that will be passed to your callbacks.
|
||||
* @param file_cb Callback function to make per file in the diff.
|
||||
@ -341,6 +344,7 @@ GIT_EXTERN(int) git_diff_merge(
|
||||
* @param line_cb Optional callback to make per line of diff text. This
|
||||
* same callback will be made for context lines, added, and
|
||||
* removed lines, and even for a deleted trailing newline.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_foreach(
|
||||
git_diff_list *diff,
|
||||
@ -351,6 +355,14 @@ GIT_EXTERN(int) git_diff_foreach(
|
||||
|
||||
/**
|
||||
* Iterate over a diff generating text output like "git diff --name-status".
|
||||
*
|
||||
* Returning a non-zero value from the callbacks will terminate the
|
||||
* iteration and cause this return `GIT_EUSER`.
|
||||
*
|
||||
* @param diff A git_diff_list generated by one of the above functions.
|
||||
* @param cb_data Reference pointer that will be passed to your callback.
|
||||
* @param print_cb Callback to make per line of diff text.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_print_compact(
|
||||
git_diff_list *diff,
|
||||
@ -362,6 +374,9 @@ GIT_EXTERN(int) git_diff_print_compact(
|
||||
*
|
||||
* This is a super easy way to generate a patch from a diff.
|
||||
*
|
||||
* Returning a non-zero value from the callbacks will terminate the
|
||||
* iteration and cause this return `GIT_EUSER`.
|
||||
*
|
||||
* @param diff A git_diff_list generated by one of the above functions.
|
||||
* @param cb_data Reference pointer that will be passed to your callbacks.
|
||||
* @param print_cb Callback function to output lines of the diff. This
|
||||
@ -369,6 +384,7 @@ GIT_EXTERN(int) git_diff_print_compact(
|
||||
* headers, and diff lines. Fortunately, you can probably
|
||||
* use various GIT_DIFF_LINE constants to determine what
|
||||
* text you are given.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_print_patch(
|
||||
git_diff_list *diff,
|
||||
@ -393,6 +409,8 @@ GIT_EXTERN(int) git_diff_print_patch(
|
||||
* When at least one of the blobs being dealt with is binary, the
|
||||
* `git_diff_delta` binary attribute will be set to 1 and no call to the
|
||||
* hunk_cb nor line_cb will be made.
|
||||
*
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_blobs(
|
||||
git_blob *old_blob,
|
||||
|
@ -25,6 +25,7 @@ enum {
|
||||
GIT_EEXISTS = -4,
|
||||
GIT_EAMBIGUOUS = -5,
|
||||
GIT_EBUFS = -6,
|
||||
GIT_EUSER = -7,
|
||||
|
||||
GIT_PASSTHROUGH = -30,
|
||||
GIT_REVWALKOVER = -31,
|
||||
|
@ -119,19 +119,21 @@ typedef struct {
|
||||
*
|
||||
* @param repo Repository where to find the notes.
|
||||
*
|
||||
* @param notes_ref OID reference to read from (optional); defaults to "refs/notes/commits".
|
||||
* @param notes_ref OID reference to read from (optional); defaults to
|
||||
* "refs/notes/commits".
|
||||
*
|
||||
* @param note_cb Callback to invoke per found annotation.
|
||||
* @param note_cb Callback to invoke per found annotation. Return non-zero
|
||||
* to stop looping.
|
||||
*
|
||||
* @param payload Extra parameter to callback function.
|
||||
*
|
||||
* @return 0 or an error code.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_note_foreach(
|
||||
git_repository *repo,
|
||||
const char *notes_ref,
|
||||
int (*note_cb)(git_note_data *note_data, void *payload),
|
||||
void *payload
|
||||
git_repository *repo,
|
||||
const char *notes_ref,
|
||||
int (*note_cb)(git_note_data *note_data, void *payload),
|
||||
void *payload
|
||||
);
|
||||
|
||||
/** @} */
|
||||
|
@ -176,13 +176,14 @@ GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
|
||||
* List all objects available in the database
|
||||
*
|
||||
* The callback will be called for each object available in the
|
||||
* database. Note that the objects are likely to be returned in the
|
||||
* index order, which would make accessing the objects in that order
|
||||
* inefficient.
|
||||
* database. Note that the objects are likely to be returned in the index
|
||||
* order, which would make accessing the objects in that order inefficient.
|
||||
* Return a non-zero value from the callback to stop looping.
|
||||
*
|
||||
* @param db database to use
|
||||
* @param cb the callback to call for each object
|
||||
* @param data data to pass to the callback
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_foreach(git_odb *db, int (*cb)(git_oid *oid, void *data), void *data);
|
||||
|
||||
|
@ -268,14 +268,15 @@ GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo, un
|
||||
*
|
||||
* The `callback` function will be called for each of the references
|
||||
* in the repository, and will receive the name of the reference and
|
||||
* the `payload` value passed to this method.
|
||||
* the `payload` value passed to this method. Returning a non-zero
|
||||
* value from the callback will terminate the iteration.
|
||||
*
|
||||
* @param repo Repository where to find the refs
|
||||
* @param list_flags Filtering flags for the reference
|
||||
* listing.
|
||||
* @param callback Function which will be called for every listed ref
|
||||
* @param payload Additional data to pass to the callback
|
||||
* @return 0 or an error code
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_foreach(git_repository *repo, unsigned int list_flags, int (*callback)(const char *, void *), void *payload);
|
||||
|
||||
|
@ -163,9 +163,12 @@ GIT_EXTERN(int) git_remote_connect(git_remote *remote, int direction);
|
||||
* The remote (or more exactly its transport) must be connected. The
|
||||
* memory belongs to the remote.
|
||||
*
|
||||
* If you a return a non-zero value from the callback, this will stop
|
||||
* looping over the refs.
|
||||
*
|
||||
* @param refs where to store the refs
|
||||
* @param remote the remote
|
||||
* @return 0 or an error code
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload);
|
||||
|
||||
|
@ -38,11 +38,11 @@ enum {
|
||||
*
|
||||
* The callback is passed the path of the file, the status and the data
|
||||
* pointer passed to this function. If the callback returns something other
|
||||
* than 0, this function will return that value.
|
||||
* than 0, this function will stop looping and return GIT_EUSER.
|
||||
*
|
||||
* @param repo a repository object
|
||||
* @param callback the function to call on each file
|
||||
* @return 0 on success or the return value of the callback that was non-zero
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_status_foreach(
|
||||
git_repository *repo,
|
||||
|
@ -128,6 +128,17 @@ GIT_EXTERN(const git_tree_entry *) git_tree_entry_byname(git_tree *tree, const c
|
||||
*/
|
||||
GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex(git_tree *tree, size_t idx);
|
||||
|
||||
/**
|
||||
* Lookup a tree entry by SHA value.
|
||||
*
|
||||
* Warning: this must examine every entry in the tree, so it is not fast.
|
||||
*
|
||||
* @param tree a previously loaded tree.
|
||||
* @param oid the sha being looked for
|
||||
* @return the tree entry; NULL if not found
|
||||
*/
|
||||
GIT_EXTERN(const git_tree_entry *) git_tree_entry_byoid(git_tree *tree, const git_oid *oid);
|
||||
|
||||
/**
|
||||
* Get the UNIX file attributes of a tree entry
|
||||
*
|
||||
|
11
src/attr.c
11
src/attr.c
@ -182,11 +182,14 @@ int git_attr_foreach(
|
||||
continue;
|
||||
|
||||
git_strmap_insert(seen, assign->name, assign, error);
|
||||
if (error >= 0)
|
||||
error = callback(assign->name, assign->value, payload);
|
||||
|
||||
if (error != 0)
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
|
||||
error = callback(assign->name, assign->value, payload);
|
||||
if (error) {
|
||||
error = GIT_EUSER;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,8 +218,10 @@ static int file_foreach(
|
||||
continue;
|
||||
|
||||
/* abort iterator on non-zero return value */
|
||||
if ((result = fn(key, var->value, data)) != 0)
|
||||
if (fn(key, var->value, data)) {
|
||||
result = GIT_EUSER;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -23,6 +23,7 @@ typedef struct {
|
||||
unsigned int index;
|
||||
git_diff_delta *delta;
|
||||
git_diff_range range;
|
||||
int error;
|
||||
} diff_output_info;
|
||||
|
||||
static int read_next_int(const char **str, int *value)
|
||||
@ -49,25 +50,24 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
|
||||
|
||||
/* expect something of the form "@@ -%d[,%d] +%d[,%d] @@" */
|
||||
if (*scan != '@')
|
||||
return -1;
|
||||
info->error = -1;
|
||||
else if (read_next_int(&scan, &range.old_start) < 0)
|
||||
info->error = -1;
|
||||
else if (*scan == ',' && read_next_int(&scan, &range.old_lines) < 0)
|
||||
info->error = -1;
|
||||
else if (read_next_int(&scan, &range.new_start) < 0)
|
||||
info->error = -1;
|
||||
else if (*scan == ',' && read_next_int(&scan, &range.new_lines) < 0)
|
||||
info->error = -1;
|
||||
else if (range.old_start < 0 || range.new_start < 0)
|
||||
info->error = -1;
|
||||
else {
|
||||
memcpy(&info->range, &range, sizeof(git_diff_range));
|
||||
|
||||
if (read_next_int(&scan, &range.old_start) < 0)
|
||||
return -1;
|
||||
if (*scan == ',' && read_next_int(&scan, &range.old_lines) < 0)
|
||||
return -1;
|
||||
|
||||
if (read_next_int(&scan, &range.new_start) < 0)
|
||||
return -1;
|
||||
if (*scan == ',' && read_next_int(&scan, &range.new_lines) < 0)
|
||||
return -1;
|
||||
|
||||
if (range.old_start < 0 || range.new_start < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(&info->range, &range, sizeof(git_diff_range));
|
||||
|
||||
return info->hunk_cb(
|
||||
info->cb_data, info->delta, &range, bufs[0].ptr, bufs[0].size);
|
||||
if (info->hunk_cb(
|
||||
info->cb_data, info->delta, &range, bufs[0].ptr, bufs[0].size))
|
||||
info->error = GIT_EUSER;
|
||||
}
|
||||
}
|
||||
|
||||
if ((len == 2 || len == 3) && info->line_cb) {
|
||||
@ -80,23 +80,24 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
|
||||
GIT_DIFF_LINE_CONTEXT;
|
||||
|
||||
if (info->line_cb(
|
||||
info->cb_data, info->delta, &info->range, origin, bufs[1].ptr, bufs[1].size) < 0)
|
||||
return -1;
|
||||
info->cb_data, info->delta, &info->range, origin, bufs[1].ptr, bufs[1].size))
|
||||
info->error = GIT_EUSER;
|
||||
|
||||
/* This should only happen if we are adding a line that does not
|
||||
* have a newline at the end and the old code did. In that case,
|
||||
* we have a ADD with a DEL_EOFNL as a pair.
|
||||
*/
|
||||
if (len == 3) {
|
||||
else if (len == 3) {
|
||||
origin = (origin == GIT_DIFF_LINE_ADDITION) ?
|
||||
GIT_DIFF_LINE_DEL_EOFNL : GIT_DIFF_LINE_ADD_EOFNL;
|
||||
|
||||
return info->line_cb(
|
||||
info->cb_data, info->delta, &info->range, origin, bufs[2].ptr, bufs[2].size);
|
||||
if (info->line_cb(
|
||||
info->cb_data, info->delta, &info->range, origin, bufs[2].ptr, bufs[2].size))
|
||||
info->error = GIT_EUSER;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return info->error;
|
||||
}
|
||||
|
||||
#define BINARY_DIFF_FLAGS (GIT_DIFF_FILE_BINARY|GIT_DIFF_FILE_NOT_BINARY)
|
||||
@ -318,6 +319,7 @@ int git_diff_foreach(
|
||||
xdemitconf_t xdiff_config;
|
||||
xdemitcb_t xdiff_callback;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.diff = diff;
|
||||
info.cb_data = data;
|
||||
info.hunk_cb = hunk_cb;
|
||||
@ -422,11 +424,11 @@ int git_diff_foreach(
|
||||
* diffs to tell if a file has really been changed.
|
||||
*/
|
||||
|
||||
if (file_cb != NULL) {
|
||||
error = file_cb(
|
||||
data, delta, (float)info.index / diff->deltas.length);
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
if (file_cb != NULL &&
|
||||
file_cb(data, delta, (float)info.index / diff->deltas.length))
|
||||
{
|
||||
error = GIT_EUSER;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* don't do hunk and line diffs if file is binary */
|
||||
@ -451,6 +453,7 @@ int git_diff_foreach(
|
||||
|
||||
xdl_diff(&old_xdiff_data, &new_xdiff_data,
|
||||
&xdiff_params, &xdiff_config, &xdiff_callback);
|
||||
error = info.error;
|
||||
|
||||
cleanup:
|
||||
release_content(&delta->old_file, &old_data, old_blob);
|
||||
@ -524,7 +527,11 @@ static int print_compact(void *data, git_diff_delta *delta, float progress)
|
||||
if (git_buf_oom(pi->buf))
|
||||
return -1;
|
||||
|
||||
return pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
|
||||
if (pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR,
|
||||
git_buf_cstr(pi->buf), git_buf_len(pi->buf)))
|
||||
return GIT_EUSER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_diff_print_compact(
|
||||
@ -586,7 +593,6 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
|
||||
const char *oldpath = delta->old_file.path;
|
||||
const char *newpfx = pi->diff->opts.new_prefix;
|
||||
const char *newpath = delta->new_file.path;
|
||||
int result;
|
||||
|
||||
GIT_UNUSED(progress);
|
||||
|
||||
@ -619,9 +625,8 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
|
||||
if (git_buf_oom(pi->buf))
|
||||
return -1;
|
||||
|
||||
result = pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
|
||||
if (result < 0)
|
||||
return result;
|
||||
if (pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf)))
|
||||
return GIT_EUSER;
|
||||
|
||||
if (delta->binary != 1)
|
||||
return 0;
|
||||
@ -633,7 +638,11 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
|
||||
if (git_buf_oom(pi->buf))
|
||||
return -1;
|
||||
|
||||
return pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_BINARY, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
|
||||
if (pi->print_cb(pi->cb_data, delta, NULL, GIT_DIFF_LINE_BINARY,
|
||||
git_buf_cstr(pi->buf), git_buf_len(pi->buf)))
|
||||
return GIT_EUSER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_patch_hunk(
|
||||
@ -649,7 +658,11 @@ static int print_patch_hunk(
|
||||
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0)
|
||||
return -1;
|
||||
|
||||
return pi->print_cb(pi->cb_data, d, r, GIT_DIFF_LINE_HUNK_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
|
||||
if (pi->print_cb(pi->cb_data, d, r, GIT_DIFF_LINE_HUNK_HDR,
|
||||
git_buf_cstr(pi->buf), git_buf_len(pi->buf)))
|
||||
return GIT_EUSER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_patch_line(
|
||||
@ -674,7 +687,11 @@ static int print_patch_line(
|
||||
if (git_buf_oom(pi->buf))
|
||||
return -1;
|
||||
|
||||
return pi->print_cb(pi->cb_data, delta, range, line_origin, git_buf_cstr(pi->buf), git_buf_len(pi->buf));
|
||||
if (pi->print_cb(pi->cb_data, delta, range, line_origin,
|
||||
git_buf_cstr(pi->buf), git_buf_len(pi->buf)))
|
||||
return GIT_EUSER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_diff_print_patch(
|
||||
@ -763,11 +780,8 @@ int git_diff_blobs(
|
||||
if (file_is_binary_by_content(&delta, &old_map, &new_map) < 0)
|
||||
return -1;
|
||||
|
||||
if (file_cb != NULL) {
|
||||
int error = file_cb(cb_data, &delta, 1);
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
if (file_cb != NULL && file_cb(cb_data, &delta, 1))
|
||||
return GIT_EUSER;
|
||||
|
||||
/* don't do hunk and line diffs if the two blobs are identical */
|
||||
if (delta.status == GIT_DELTA_UNMODIFIED)
|
||||
@ -777,6 +791,7 @@ int git_diff_blobs(
|
||||
if (delta.binary == 1)
|
||||
return 0;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.diff = NULL;
|
||||
info.delta = δ
|
||||
info.cb_data = cb_data;
|
||||
@ -790,5 +805,5 @@ int git_diff_blobs(
|
||||
|
||||
xdl_diff(&old_data, &new_data, &xdiff_params, &xdiff_config, &xdiff_callback);
|
||||
|
||||
return 0;
|
||||
return info.error;
|
||||
}
|
||||
|
43
src/notes.c
43
src/notes.c
@ -527,9 +527,9 @@ static int process_entry_path(
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
git_note_data note_data;
|
||||
|
||||
if (git_buf_puts(&buf, entry_path) < 0)
|
||||
if ((error = git_buf_puts(&buf, entry_path)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
len = git_buf_len(&buf);
|
||||
|
||||
while (i < len) {
|
||||
@ -537,10 +537,9 @@ static int process_entry_path(
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (git__fromhex(buf.ptr[i]) < 0) {
|
||||
/* This is not a note entry */
|
||||
error = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -556,16 +555,17 @@ static int process_entry_path(
|
||||
|
||||
if (j != GIT_OID_HEXSZ) {
|
||||
/* This is not a note entry */
|
||||
error = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (git_oid_fromstr(¬e_data.annotated_object_oid, buf.ptr) < 0)
|
||||
return -1;
|
||||
if ((error = git_oid_fromstr(
|
||||
¬e_data.annotated_object_oid, buf.ptr)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
git_oid_cpy(¬e_data.blob_oid, note_oid);
|
||||
|
||||
error = note_cb(¬e_data, payload);
|
||||
if (note_cb(¬e_data, payload))
|
||||
error = GIT_EUSER;
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&buf);
|
||||
@ -578,34 +578,27 @@ int git_note_foreach(
|
||||
int (*note_cb)(git_note_data *note_data, void *payload),
|
||||
void *payload)
|
||||
{
|
||||
int error = -1;
|
||||
int error;
|
||||
git_iterator *iter = NULL;
|
||||
git_tree *tree = NULL;
|
||||
git_commit *commit = NULL;
|
||||
const git_index_entry *item;
|
||||
|
||||
if ((error = retrieve_note_tree_and_commit(&tree, &commit, repo, ¬es_ref)) < 0)
|
||||
goto cleanup;
|
||||
if (!(error = retrieve_note_tree_and_commit(
|
||||
&tree, &commit, repo, ¬es_ref)) &&
|
||||
!(error = git_iterator_for_tree(&iter, repo, tree)))
|
||||
error = git_iterator_current(iter, &item);
|
||||
|
||||
if (git_iterator_for_tree(&iter, repo, tree) < 0)
|
||||
goto cleanup;
|
||||
while (!error && item) {
|
||||
error = process_entry_path(item->path, &item->oid, note_cb, payload);
|
||||
|
||||
if (git_iterator_current(iter, &item) < 0)
|
||||
goto cleanup;
|
||||
|
||||
while (item) {
|
||||
if (process_entry_path(item->path, &item->oid, note_cb, payload) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_iterator_advance(iter, &item) < 0)
|
||||
goto cleanup;
|
||||
if (!error)
|
||||
error = git_iterator_advance(iter, &item);
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
||||
cleanup:
|
||||
git_iterator_free(iter);
|
||||
git_tree_free(tree);
|
||||
git_commit_free(commit);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -609,9 +609,12 @@ int git_odb_foreach(git_odb *db, int (*cb)(git_oid *oid, void *data), void *data
|
||||
{
|
||||
unsigned int i;
|
||||
backend_internal *internal;
|
||||
|
||||
git_vector_foreach(&db->backends, i, internal) {
|
||||
git_odb_backend *b = internal->backend;
|
||||
b->foreach(b, cb, data);
|
||||
int error = b->foreach(b, cb, data);
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -680,6 +680,7 @@ struct foreach_state {
|
||||
size_t dir_len;
|
||||
int (*cb)(git_oid *oid, void *data);
|
||||
void *data;
|
||||
int cb_error;
|
||||
};
|
||||
|
||||
GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
|
||||
@ -718,8 +719,10 @@ static int foreach_object_dir_cb(void *_state, git_buf *path)
|
||||
if (filename_to_oid(&oid, path->ptr + state->dir_len) < 0)
|
||||
return 0;
|
||||
|
||||
if (state->cb(&oid, state->data) < 0)
|
||||
if (state->cb(&oid, state->data)) {
|
||||
state->cb_error = GIT_EUSER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -728,10 +731,7 @@ static int foreach_cb(void *_state, git_buf *path)
|
||||
{
|
||||
struct foreach_state *state = (struct foreach_state *) _state;
|
||||
|
||||
if (git_path_direach(path, foreach_object_dir_cb, state) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return git_path_direach(path, foreach_object_dir_cb, state);
|
||||
}
|
||||
|
||||
static int loose_backend__foreach(git_odb_backend *_backend, int (*cb)(git_oid *oid, void *data), void *data)
|
||||
@ -749,14 +749,16 @@ static int loose_backend__foreach(git_odb_backend *_backend, int (*cb)(git_oid *
|
||||
git_buf_sets(&buf, objects_dir);
|
||||
git_path_to_dir(&buf);
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.cb = cb;
|
||||
state.data = data;
|
||||
state.dir_len = git_buf_len(&buf);
|
||||
|
||||
error = git_path_direach(&buf, foreach_cb, &state);
|
||||
|
||||
git_buf_free(&buf);
|
||||
|
||||
return error;
|
||||
return state.cb_error ? state.cb_error : error;
|
||||
}
|
||||
|
||||
static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
|
||||
|
@ -422,6 +422,7 @@ static int pack_backend__exists(git_odb_backend *backend, const git_oid *oid)
|
||||
|
||||
static int pack_backend__foreach(git_odb_backend *_backend, int (*cb)(git_oid *oid, void *data), void *data)
|
||||
{
|
||||
int error;
|
||||
struct git_pack_file *p;
|
||||
struct pack_backend *backend;
|
||||
unsigned int i;
|
||||
@ -430,12 +431,14 @@ static int pack_backend__foreach(git_odb_backend *_backend, int (*cb)(git_oid *o
|
||||
backend = (struct pack_backend *)_backend;
|
||||
|
||||
/* Make sure we know about the packfiles */
|
||||
if (packfile_refresh_all(backend) < 0)
|
||||
return -1;
|
||||
if ((error = packfile_refresh_all(backend)) < 0)
|
||||
return error;
|
||||
|
||||
git_vector_foreach(&backend->packs, i, p) {
|
||||
git_pack_foreach_entry(p, cb, &data);
|
||||
if ((error = git_pack_foreach_entry(p, cb, &data)) < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
11
src/pack.c
11
src/pack.c
@ -687,10 +687,9 @@ static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_
|
||||
}
|
||||
|
||||
int git_pack_foreach_entry(
|
||||
struct git_pack_file *p,
|
||||
int (*cb)(git_oid *oid, void *data),
|
||||
void *data)
|
||||
|
||||
struct git_pack_file *p,
|
||||
int (*cb)(git_oid *oid, void *data),
|
||||
void *data)
|
||||
{
|
||||
const unsigned char *index = p->index_map.data, *current;
|
||||
unsigned stride;
|
||||
@ -722,7 +721,9 @@ int git_pack_foreach_entry(
|
||||
|
||||
current = index;
|
||||
for (i = 0; i < p->num_objects; i++) {
|
||||
cb((git_oid *)current, data);
|
||||
if (cb((git_oid *)current, data))
|
||||
return GIT_EUSER;
|
||||
|
||||
current += stride;
|
||||
}
|
||||
|
||||
|
@ -217,6 +217,7 @@ extern int git_path_apply_relative(git_buf *target, const char *relpath);
|
||||
* the input state and the second arg is pathbuf. The function
|
||||
* may modify the pathbuf, but only by appending new text.
|
||||
* @param state to pass to fn as the first arg.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
*/
|
||||
extern int git_path_direach(
|
||||
git_buf *pathbuf,
|
||||
|
22
src/refs.c
22
src/refs.c
@ -500,6 +500,7 @@ struct dirent_list_data {
|
||||
|
||||
int (*callback)(const char *, void *);
|
||||
void *callback_payload;
|
||||
int callback_error;
|
||||
};
|
||||
|
||||
static int _dirent_loose_listall(void *_data, git_buf *full_path)
|
||||
@ -520,7 +521,10 @@ static int _dirent_loose_listall(void *_data, git_buf *full_path)
|
||||
return 0; /* we are filtering out this reference */
|
||||
}
|
||||
|
||||
return data->callback(file_path, data->callback_payload);
|
||||
if (data->callback(file_path, data->callback_payload))
|
||||
data->callback_error = GIT_EUSER;
|
||||
|
||||
return data->callback_error;
|
||||
}
|
||||
|
||||
static int _dirent_loose_load(void *data, git_buf *full_path)
|
||||
@ -843,15 +847,17 @@ static int reference_path_available(
|
||||
const char *ref,
|
||||
const char* old_ref)
|
||||
{
|
||||
int error;
|
||||
struct reference_available_t data;
|
||||
|
||||
data.new_ref = ref;
|
||||
data.old_ref = old_ref;
|
||||
data.available = 1;
|
||||
|
||||
if (git_reference_foreach(repo, GIT_REF_LISTALL,
|
||||
_reference_available_cb, (void *)&data) < 0)
|
||||
return -1;
|
||||
error = git_reference_foreach(
|
||||
repo, GIT_REF_LISTALL, _reference_available_cb, (void *)&data);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (!data.available) {
|
||||
giterr_set(GITERR_REFERENCE,
|
||||
@ -1486,8 +1492,8 @@ int git_reference_foreach(
|
||||
return -1;
|
||||
|
||||
git_strmap_foreach(repo->references.packfile, ref_name, ref, {
|
||||
if (callback(ref_name, payload) < 0)
|
||||
return 0;
|
||||
if (callback(ref_name, payload))
|
||||
return GIT_EUSER;
|
||||
});
|
||||
}
|
||||
|
||||
@ -1499,14 +1505,16 @@ int git_reference_foreach(
|
||||
data.repo = repo;
|
||||
data.callback = callback;
|
||||
data.callback_payload = payload;
|
||||
data.callback_error = 0;
|
||||
|
||||
if (git_buf_joinpath(&refs_path, repo->path_repository, GIT_REFS_DIR) < 0)
|
||||
return -1;
|
||||
|
||||
result = git_path_direach(&refs_path, _dirent_loose_listall, &data);
|
||||
|
||||
git_buf_free(&refs_path);
|
||||
|
||||
return result;
|
||||
return data.callback_error ? GIT_EUSER : result;
|
||||
}
|
||||
|
||||
static int cb__reflist_add(const char *ref, void *data)
|
||||
|
22
src/status.c
22
src/status.c
@ -114,7 +114,8 @@ int git_status_foreach_ext(
|
||||
if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) {
|
||||
for (i = 0; !err && i < idx2head->deltas.length; i++) {
|
||||
i2h = GIT_VECTOR_GET(&idx2head->deltas, i);
|
||||
err = cb(i2h->old_file.path, index_delta2status(i2h->status), cbdata);
|
||||
if (cb(i2h->old_file.path, index_delta2status(i2h->status), cbdata))
|
||||
err = GIT_EUSER;
|
||||
}
|
||||
git_diff_list_free(idx2head);
|
||||
idx2head = NULL;
|
||||
@ -130,14 +131,17 @@ int git_status_foreach_ext(
|
||||
cmp = !w2i ? -1 : !i2h ? 1 : strcmp(i2h->old_file.path, w2i->old_file.path);
|
||||
|
||||
if (cmp < 0) {
|
||||
err = cb(i2h->old_file.path, index_delta2status(i2h->status), cbdata);
|
||||
if (cb(i2h->old_file.path, index_delta2status(i2h->status), cbdata))
|
||||
err = GIT_EUSER;
|
||||
i++;
|
||||
} else if (cmp > 0) {
|
||||
err = cb(w2i->old_file.path, workdir_delta2status(w2i->status), cbdata);
|
||||
if (cb(w2i->old_file.path, workdir_delta2status(w2i->status), cbdata))
|
||||
err = GIT_EUSER;
|
||||
j++;
|
||||
} else {
|
||||
err = cb(i2h->old_file.path, index_delta2status(i2h->status) |
|
||||
workdir_delta2status(w2i->status), cbdata);
|
||||
if (cb(i2h->old_file.path, index_delta2status(i2h->status) |
|
||||
workdir_delta2status(w2i->status), cbdata))
|
||||
err = GIT_EUSER;
|
||||
i++; j++;
|
||||
}
|
||||
}
|
||||
@ -146,6 +150,7 @@ cleanup:
|
||||
git_tree_free(head);
|
||||
git_diff_list_free(idx2head);
|
||||
git_diff_list_free(wd2idx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -166,9 +171,10 @@ int git_status_foreach(
|
||||
}
|
||||
|
||||
struct status_file_info {
|
||||
char *expected;
|
||||
unsigned int count;
|
||||
unsigned int status;
|
||||
char *expected;
|
||||
int ambiguous;
|
||||
};
|
||||
|
||||
static int get_one_status(const char *path, unsigned int status, void *data)
|
||||
@ -183,6 +189,7 @@ static int get_one_status(const char *path, unsigned int status, void *data)
|
||||
p_fnmatch(sfi->expected, path, 0) != 0)) {
|
||||
giterr_set(GITERR_INVALID,
|
||||
"Ambiguous path '%s' given to git_status_file", sfi->expected);
|
||||
sfi->ambiguous = true;
|
||||
return GIT_EAMBIGUOUS;
|
||||
}
|
||||
|
||||
@ -215,6 +222,9 @@ int git_status_file(
|
||||
|
||||
error = git_status_foreach_ext(repo, &opts, get_one_status, &sfi);
|
||||
|
||||
if (error < 0 && sfi.ambiguous)
|
||||
error = GIT_EAMBIGUOUS;
|
||||
|
||||
if (!error && !sfi.count) {
|
||||
giterr_set(GITERR_INVALID,
|
||||
"Attempt to get status of nonexistent file '%s'", path);
|
||||
|
36
src/tree.c
36
src/tree.c
@ -240,6 +240,21 @@ const git_tree_entry *git_tree_entry_byindex(git_tree *tree, size_t idx)
|
||||
return git_vector_get(&tree->entries, idx);
|
||||
}
|
||||
|
||||
const git_tree_entry *git_tree_entry_byoid(git_tree *tree, const git_oid *oid)
|
||||
{
|
||||
unsigned int i;
|
||||
git_tree_entry *e;
|
||||
|
||||
assert(tree);
|
||||
|
||||
git_vector_foreach(&tree->entries, i, e) {
|
||||
if (memcmp(&e->oid.id, &oid->id, sizeof(oid->id)) == 0)
|
||||
return e;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int git_tree__prefix_position(git_tree *tree, const char *path)
|
||||
{
|
||||
git_vector *entries = &tree->entries;
|
||||
@ -724,7 +739,7 @@ int git_tree_entry_bypath(
|
||||
}
|
||||
|
||||
switch (path[filename_len]) {
|
||||
case '/':
|
||||
case '/':
|
||||
/* If there are more components in the path...
|
||||
* then this entry *must* be a tree */
|
||||
if (!git_tree_entry__is_tree(entry)) {
|
||||
@ -772,8 +787,10 @@ static int tree_walk(
|
||||
for (i = 0; i < tree->entries.length; ++i) {
|
||||
git_tree_entry *entry = tree->entries.contents[i];
|
||||
|
||||
if (preorder && callback(path->ptr, entry, payload) < 0)
|
||||
return -1;
|
||||
if (preorder && callback(path->ptr, entry, payload)) {
|
||||
error = GIT_EUSER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (git_tree_entry__is_tree(entry)) {
|
||||
git_tree *subtree;
|
||||
@ -790,18 +807,21 @@ static int tree_walk(
|
||||
if (git_buf_oom(path))
|
||||
return -1;
|
||||
|
||||
if (tree_walk(subtree, callback, path, payload, preorder) < 0)
|
||||
return -1;
|
||||
error = tree_walk(subtree, callback, path, payload, preorder);
|
||||
if (error != 0)
|
||||
break;
|
||||
|
||||
git_buf_truncate(path, path_len);
|
||||
git_tree_free(subtree);
|
||||
}
|
||||
|
||||
if (!preorder && callback(path->ptr, entry, payload) < 0)
|
||||
return -1;
|
||||
if (!preorder && callback(path->ptr, entry, payload)) {
|
||||
error = GIT_EUSER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_tree_walk(git_tree *tree, git_treewalk_cb callback, int mode, void *payload)
|
||||
|
@ -113,6 +113,22 @@ static int count_attrs(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cancel_iteration(
|
||||
const char *name,
|
||||
const char *value,
|
||||
void *payload)
|
||||
{
|
||||
GIT_UNUSED(name);
|
||||
GIT_UNUSED(value);
|
||||
|
||||
*((int *)payload) -= 1;
|
||||
|
||||
if (*((int *)payload) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_attr_repo__foreach(void)
|
||||
{
|
||||
int count;
|
||||
@ -131,6 +147,12 @@ void test_attr_repo__foreach(void)
|
||||
cl_git_pass(git_attr_foreach(g_repo, 0, "sub/subdir_test2.txt",
|
||||
&count_attrs, &count));
|
||||
cl_assert(count == 6); /* repoattr, rootattr, subattr, reposub, negattr, another */
|
||||
|
||||
count = 2;
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_attr_foreach(
|
||||
g_repo, 0, "sub/subdir_test1", &cancel_iteration, &count)
|
||||
);
|
||||
}
|
||||
|
||||
void test_attr_repo__manpage_example(void)
|
||||
|
@ -226,7 +226,7 @@ void test_config_read__foreach(void)
|
||||
|
||||
count = 3;
|
||||
cl_git_fail(ret = git_config_foreach(cfg, cfg_callback_countdown, &count));
|
||||
cl_assert_equal_i(-100, ret);
|
||||
cl_assert_equal_i(GIT_EUSER, ret);
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
@ -90,3 +90,53 @@ void test_diff_index__0(void)
|
||||
git_tree_free(a);
|
||||
git_tree_free(b);
|
||||
}
|
||||
|
||||
static int diff_stop_after_2_files(
|
||||
void *cb_data,
|
||||
git_diff_delta *delta,
|
||||
float progress)
|
||||
{
|
||||
diff_expects *e = cb_data;
|
||||
|
||||
GIT_UNUSED(progress);
|
||||
GIT_UNUSED(delta);
|
||||
|
||||
e->files++;
|
||||
|
||||
return (e->files == 2);
|
||||
}
|
||||
|
||||
void test_diff_index__1(void)
|
||||
{
|
||||
/* grabbed a couple of commit oids from the history of the attr repo */
|
||||
const char *a_commit = "26a125ee1bf"; /* the current HEAD */
|
||||
const char *b_commit = "0017bd4ab1ec3"; /* the start */
|
||||
git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit);
|
||||
git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit);
|
||||
git_diff_options opts = {0};
|
||||
git_diff_list *diff = NULL;
|
||||
diff_expects exp;
|
||||
|
||||
cl_assert(a);
|
||||
cl_assert(b);
|
||||
|
||||
opts.context_lines = 1;
|
||||
opts.interhunk_lines = 1;
|
||||
|
||||
memset(&exp, 0, sizeof(exp));
|
||||
|
||||
cl_git_pass(git_diff_index_to_tree(g_repo, &opts, a, &diff));
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER,
|
||||
git_diff_foreach(diff, &exp, diff_stop_after_2_files, NULL, NULL)
|
||||
);
|
||||
|
||||
cl_assert(exp.files == 2);
|
||||
|
||||
git_diff_list_free(diff);
|
||||
diff = NULL;
|
||||
|
||||
git_tree_free(a);
|
||||
git_tree_free(b);
|
||||
}
|
||||
|
@ -95,11 +95,39 @@ void test_notes_notes__can_retrieve_a_list_of_notes_for_a_given_namespace(void)
|
||||
create_note(¬e_oid3, "refs/notes/i-can-see-dead-notes", "9fd738e8f7967c078dceed8190330fc8648ee56a", "I decorate 9fd7 and 4a20\n");
|
||||
create_note(¬e_oid4, "refs/notes/i-can-see-dead-notes", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "I decorate 9fd7 and 4a20\n");
|
||||
|
||||
cl_git_pass(git_note_foreach(_repo, "refs/notes/i-can-see-dead-notes", note_list_cb, &retrieved_notes));
|
||||
cl_git_pass(git_note_foreach
|
||||
(_repo, "refs/notes/i-can-see-dead-notes", note_list_cb, &retrieved_notes));
|
||||
|
||||
cl_assert_equal_i(4, retrieved_notes);
|
||||
}
|
||||
|
||||
static int note_cancel_cb(git_note_data *note_data, void *payload)
|
||||
{
|
||||
unsigned int *count = (unsigned int *)payload;
|
||||
|
||||
GIT_UNUSED(note_data);
|
||||
|
||||
(*count)++;
|
||||
|
||||
return (*count > 2);
|
||||
}
|
||||
|
||||
void test_notes_notes__can_cancel_foreach(void)
|
||||
{
|
||||
git_oid note_oid1, note_oid2, note_oid3, note_oid4;
|
||||
unsigned int retrieved_notes = 0;
|
||||
|
||||
create_note(¬e_oid1, "refs/notes/i-can-see-dead-notes", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "I decorate a65f\n");
|
||||
create_note(¬e_oid2, "refs/notes/i-can-see-dead-notes", "c47800c7266a2be04c571c04d5a6614691ea99bd", "I decorate c478\n");
|
||||
create_note(¬e_oid3, "refs/notes/i-can-see-dead-notes", "9fd738e8f7967c078dceed8190330fc8648ee56a", "I decorate 9fd7 and 4a20\n");
|
||||
create_note(¬e_oid4, "refs/notes/i-can-see-dead-notes", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "I decorate 9fd7 and 4a20\n");
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER,
|
||||
git_note_foreach(_repo, "refs/notes/i-can-see-dead-notes",
|
||||
note_cancel_cb, &retrieved_notes));
|
||||
}
|
||||
|
||||
void test_notes_notes__retrieving_a_list_of_notes_for_an_unknown_namespace_returns_ENOTFOUND(void)
|
||||
{
|
||||
int error;
|
||||
|
103
tests-clar/object/tree/walk.c
Normal file
103
tests-clar/object/tree/walk.c
Normal file
@ -0,0 +1,103 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "tree.h"
|
||||
|
||||
static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
|
||||
static git_repository *g_repo;
|
||||
|
||||
void test_object_tree_walk__initialize(void)
|
||||
{
|
||||
g_repo = cl_git_sandbox_init("testrepo");
|
||||
}
|
||||
|
||||
void test_object_tree_walk__cleanup(void)
|
||||
{
|
||||
cl_git_sandbox_cleanup();
|
||||
}
|
||||
|
||||
static int treewalk_count_cb(
|
||||
const char *root, const git_tree_entry *entry, void *payload)
|
||||
{
|
||||
int *count = payload;
|
||||
|
||||
GIT_UNUSED(root);
|
||||
GIT_UNUSED(entry);
|
||||
|
||||
(*count) += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_object_tree_walk__0(void)
|
||||
{
|
||||
git_oid id;
|
||||
git_tree *tree;
|
||||
int ct;
|
||||
|
||||
git_oid_fromstr(&id, tree_oid);
|
||||
|
||||
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
|
||||
|
||||
ct = 0;
|
||||
cl_git_pass(git_tree_walk(tree, treewalk_count_cb, GIT_TREEWALK_PRE, &ct));
|
||||
cl_assert_equal_i(3, ct);
|
||||
|
||||
ct = 0;
|
||||
cl_git_pass(git_tree_walk(tree, treewalk_count_cb, GIT_TREEWALK_POST, &ct));
|
||||
cl_assert_equal_i(3, ct);
|
||||
|
||||
git_tree_free(tree);
|
||||
}
|
||||
|
||||
|
||||
static int treewalk_stop_cb(
|
||||
const char *root, const git_tree_entry *entry, void *payload)
|
||||
{
|
||||
int *count = payload;
|
||||
|
||||
GIT_UNUSED(root);
|
||||
GIT_UNUSED(entry);
|
||||
|
||||
(*count) += 1;
|
||||
|
||||
return (*count == 2);
|
||||
}
|
||||
|
||||
static int treewalk_stop_immediately_cb(
|
||||
const char *root, const git_tree_entry *entry, void *payload)
|
||||
{
|
||||
GIT_UNUSED(root);
|
||||
GIT_UNUSED(entry);
|
||||
GIT_UNUSED(payload);
|
||||
return -100;
|
||||
}
|
||||
|
||||
void test_object_tree_walk__1(void)
|
||||
{
|
||||
git_oid id;
|
||||
git_tree *tree;
|
||||
int ct;
|
||||
|
||||
git_oid_fromstr(&id, tree_oid);
|
||||
|
||||
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
|
||||
|
||||
ct = 0;
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_tree_walk(tree, treewalk_stop_cb, GIT_TREEWALK_PRE, &ct));
|
||||
cl_assert_equal_i(2, ct);
|
||||
|
||||
ct = 0;
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_tree_walk(tree, treewalk_stop_cb, GIT_TREEWALK_POST, &ct));
|
||||
cl_assert_equal_i(2, ct);
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_tree_walk(
|
||||
tree, treewalk_stop_immediately_cb, GIT_TREEWALK_PRE, NULL));
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_tree_walk(
|
||||
tree, treewalk_stop_immediately_cb, GIT_TREEWALK_POST, NULL));
|
||||
|
||||
git_tree_free(tree);
|
||||
}
|
@ -55,3 +55,20 @@ void test_odb_foreach__one_pack(void)
|
||||
cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL));
|
||||
cl_assert(nobj == 1628);
|
||||
}
|
||||
|
||||
static int foreach_stop_cb(git_oid *oid, void *data)
|
||||
{
|
||||
GIT_UNUSED(data);
|
||||
GIT_UNUSED(oid);
|
||||
|
||||
nobj++;
|
||||
|
||||
return (nobj == 1000);
|
||||
}
|
||||
|
||||
void test_odb_foreach__interrupt_foreach(void)
|
||||
{
|
||||
nobj = 0;
|
||||
cl_assert_equal_i(GIT_EUSER, git_odb_foreach(_odb, foreach_stop_cb, NULL));
|
||||
cl_assert(nobj == 1000);
|
||||
}
|
||||
|
@ -125,3 +125,28 @@ void test_refs_branches_foreach__retrieve_remote_symbolic_HEAD_when_present(void
|
||||
assert_branch_has_been_found(exp, "nulltoken/HEAD");
|
||||
assert_branch_has_been_found(exp, "nulltoken/HEAD");
|
||||
}
|
||||
|
||||
static int branch_list_interrupt_cb(
|
||||
const char *branch_name, git_branch_t branch_type, void *payload)
|
||||
{
|
||||
int *count;
|
||||
|
||||
GIT_UNUSED(branch_type);
|
||||
GIT_UNUSED(branch_name);
|
||||
|
||||
count = (int *)payload;
|
||||
(*count)++;
|
||||
|
||||
return (*count == 5);
|
||||
}
|
||||
|
||||
void test_refs_branches_foreach__can_cancel(void)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
cl_assert_equal_i(GIT_EUSER,
|
||||
git_branch_foreach(repo, GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE,
|
||||
branch_list_interrupt_cb, &count));
|
||||
|
||||
cl_assert_equal_i(5, count);
|
||||
}
|
||||
|
@ -68,3 +68,25 @@ void test_refs_foreachglob__retrieve_partially_named_references(void)
|
||||
|
||||
assert_retrieval("*test*", GIT_REF_LISTALL, 4);
|
||||
}
|
||||
|
||||
|
||||
static int interrupt_cb(const char *reference_name, void *payload)
|
||||
{
|
||||
int *count = (int *)payload;
|
||||
|
||||
GIT_UNUSED(reference_name);
|
||||
|
||||
(*count)++;
|
||||
|
||||
return (*count == 11);
|
||||
}
|
||||
|
||||
void test_refs_foreachglob__can_cancel(void)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
cl_assert_equal_i(GIT_EUSER, git_reference_foreach_glob(
|
||||
repo, "*", GIT_REF_LISTALL, interrupt_cb, &count) );
|
||||
|
||||
cl_assert_equal_i(11, count);
|
||||
}
|
||||
|
@ -530,7 +530,7 @@ void test_status_worktree__bracket_in_filename(void)
|
||||
|
||||
cl_git_pass(git_repository_init(&repo, "with_bracket", 0));
|
||||
cl_git_mkfile("with_bracket/" FILE_WITH_BRACKET, "I have a bracket in my name\n");
|
||||
|
||||
|
||||
/* file is new to working directory */
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
@ -578,7 +578,7 @@ void test_status_worktree__bracket_in_filename(void)
|
||||
|
||||
cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET));
|
||||
cl_assert(status_flags == GIT_STATUS_INDEX_NEW);
|
||||
|
||||
|
||||
/* Create file without bracket */
|
||||
|
||||
cl_git_mkfile("with_bracket/" FILE_WITHOUT_BRACKET, "I have no bracket in my name!\n");
|
||||
@ -591,7 +591,7 @@ void test_status_worktree__bracket_in_filename(void)
|
||||
|
||||
error = git_status_file(&status_flags, repo, FILE_WITH_BRACKET);
|
||||
cl_git_fail(error);
|
||||
cl_assert(error == GIT_EAMBIGUOUS);
|
||||
cl_assert_equal_i(GIT_EAMBIGUOUS, error);
|
||||
|
||||
git_index_free(index);
|
||||
git_repository_free(repo);
|
||||
@ -769,6 +769,31 @@ void test_status_worktree__disable_pathspec_match(void)
|
||||
cl_git_pass(
|
||||
git_status_foreach_ext(repo, &opts, cb_status__expected_path, NULL)
|
||||
);
|
||||
|
||||
|
||||
git_repository_free(repo);
|
||||
}
|
||||
|
||||
|
||||
static int cb_status__interrupt(const char *p, unsigned int s, void *payload)
|
||||
{
|
||||
volatile int *count = (int *)payload;
|
||||
|
||||
GIT_UNUSED(p);
|
||||
GIT_UNUSED(s);
|
||||
|
||||
(*count)++;
|
||||
|
||||
return (*count == 8);
|
||||
}
|
||||
|
||||
void test_status_worktree__interruptable_foreach(void)
|
||||
{
|
||||
int count = 0;
|
||||
git_repository *repo = cl_git_sandbox_init("status");
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_status_foreach(repo, cb_status__interrupt, &count)
|
||||
);
|
||||
|
||||
cl_assert_equal_i(8, count);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user