mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-06 06:33:36 +00:00
Merge pull request #1986 from libgit2/rb/error-handling-cleanups
Clean up some error handling and change callback error behavior
This commit is contained in:
commit
79194bcdc9
@ -33,6 +33,7 @@ OPTION( ANDROID "Build for android NDK" OFF )
|
||||
|
||||
OPTION( USE_ICONV "Link with and use iconv library" OFF )
|
||||
OPTION( USE_SSH "Link with libssh to enable SSH support" ON )
|
||||
OPTION( VALGRIND "Configure build for valgrind" OFF )
|
||||
|
||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
SET( USE_ICONV ON )
|
||||
@ -340,9 +341,11 @@ IF (WIN32 AND NOT CYGWIN)
|
||||
ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501)
|
||||
FILE(GLOB SRC_OS src/win32/*.c src/win32/*.h)
|
||||
ELSEIF (AMIGA)
|
||||
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R)
|
||||
FILE(GLOB SRC_OS src/amiga/*.c src/amiga/*.h)
|
||||
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R -DNO_MMAP)
|
||||
ELSE()
|
||||
IF (VALGRIND)
|
||||
ADD_DEFINITIONS(-DNO_MMAP)
|
||||
ENDIF()
|
||||
FILE(GLOB SRC_OS src/unix/*.c src/unix/*.h)
|
||||
ENDIF()
|
||||
FILE(GLOB SRC_GIT2 src/*.c src/*.h src/transports/*.c src/transports/*.h src/xdiff/*.c src/xdiff/*.h)
|
||||
|
||||
@ -199,8 +199,9 @@ typedef int (*git_attr_foreach_cb)(const char *name, const char *value, void *pa
|
||||
* 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.
|
||||
* The value will be returned from `git_attr_foreach`.
|
||||
* @param payload Passed on as extra parameter to callback function.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_attr_foreach(
|
||||
git_repository *repo,
|
||||
|
||||
@ -159,37 +159,32 @@ typedef int (*git_blob_chunk_cb)(char *content, size_t max_length, void *payload
|
||||
* Write a loose blob to the Object Database from a
|
||||
* provider of chunks of data.
|
||||
*
|
||||
* Provided the `hintpath` parameter is filled, its value
|
||||
* will help to determine what git filters should be applied
|
||||
* to the object before it can be placed to the object database.
|
||||
* If the `hintpath` parameter is filled, it will be used to determine
|
||||
* what git filters should be applied to the object before it is written
|
||||
* to the object database.
|
||||
*
|
||||
* The implementation of the callback MUST respect the following rules:
|
||||
*
|
||||
* The implementation of the callback has to respect the
|
||||
* following rules:
|
||||
* - `content` must be filled by the callback. The maximum number of
|
||||
* bytes that the buffer can accept per call is defined by the
|
||||
* `max_length` parameter. Allocation and freeing of the buffer will
|
||||
* be taken care of by libgit2.
|
||||
*
|
||||
* - `content` will have to be filled by the consumer. The maximum number
|
||||
* of bytes that the buffer can accept per call is defined by the
|
||||
* `max_length` parameter. Allocation and freeing of the buffer will be taken
|
||||
* care of by the function.
|
||||
* - The `callback` must return the number of bytes that have been
|
||||
* written to the `content` buffer.
|
||||
*
|
||||
* - The callback is expected to return the number of bytes
|
||||
* that `content` have been filled with.
|
||||
*
|
||||
* - When there is no more data to stream, the callback should
|
||||
* return 0. This will prevent it from being invoked anymore.
|
||||
*
|
||||
* - When an error occurs, the callback should return -1.
|
||||
* - When there is no more data to stream, `callback` should return
|
||||
* 0. This will prevent it from being invoked anymore.
|
||||
*
|
||||
* - If an error occurs, the callback should return a negative value.
|
||||
* This value will be returned to the caller.
|
||||
*
|
||||
* @param id Return the id of the written blob
|
||||
*
|
||||
* @param repo repository where the blob will be written.
|
||||
* This repository can be bare or not.
|
||||
*
|
||||
* @param hintpath if not NULL, will help selecting the filters
|
||||
* to apply onto the content of the blob to be created.
|
||||
*
|
||||
* @return 0 or an error code
|
||||
* @param repo Repository where the blob will be written.
|
||||
* This repository can be bare or not.
|
||||
* @param hintpath If not NULL, will be used to select data filters
|
||||
* to apply onto the content of the blob to be created.
|
||||
* @return 0 or error code (from either libgit2 or callback function)
|
||||
*/
|
||||
GIT_EXTERN(int) git_blob_create_fromchunks(
|
||||
git_oid *id,
|
||||
|
||||
@ -174,7 +174,12 @@ typedef enum {
|
||||
* - GIT_CHECKOUT_NOTIFY_IGNORED notifies about ignored files.
|
||||
*
|
||||
* Returning a non-zero value from this callback will cancel the checkout.
|
||||
* Notification callbacks are made prior to modifying any files on disk.
|
||||
* The non-zero return value will be propagated back and returned by the
|
||||
* git_checkout_... call.
|
||||
*
|
||||
* Notification callbacks are made prior to modifying any files on disk,
|
||||
* so canceling on any notification will still happen prior to any files
|
||||
* being modified.
|
||||
*/
|
||||
typedef enum {
|
||||
GIT_CHECKOUT_NOTIFY_NONE = 0,
|
||||
@ -252,9 +257,9 @@ typedef struct git_checkout_opts {
|
||||
*
|
||||
* @param repo repository to check out (must be non-bare)
|
||||
* @param opts specifies checkout options (may be NULL)
|
||||
* @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing
|
||||
* branch, GIT_ERROR otherwise (use giterr_last for information
|
||||
* about the error)
|
||||
* @return 0 on success, GIT_EUNBORNBRANCH if HEAD points to a non
|
||||
* existing branch, non-zero value returned by `notify_cb`, or
|
||||
* other error code < 0 (use giterr_last for error details)
|
||||
*/
|
||||
GIT_EXTERN(int) git_checkout_head(
|
||||
git_repository *repo,
|
||||
@ -266,8 +271,8 @@ GIT_EXTERN(int) git_checkout_head(
|
||||
* @param repo repository into which to check out (must be non-bare)
|
||||
* @param index index to be checked out (or NULL to use repository index)
|
||||
* @param opts specifies checkout options (may be NULL)
|
||||
* @return 0 on success, GIT_ERROR otherwise (use giterr_last for information
|
||||
* about the error)
|
||||
* @return 0 on success, non-zero return value from `notify_cb`, or error
|
||||
* code < 0 (use giterr_last for error details)
|
||||
*/
|
||||
GIT_EXTERN(int) git_checkout_index(
|
||||
git_repository *repo,
|
||||
@ -282,8 +287,8 @@ GIT_EXTERN(int) git_checkout_index(
|
||||
* @param treeish a commit, tag or tree which content will be used to update
|
||||
* the working directory (or NULL to use HEAD)
|
||||
* @param opts specifies checkout options (may be NULL)
|
||||
* @return 0 on success, GIT_ERROR otherwise (use giterr_last for information
|
||||
* about the error)
|
||||
* @return 0 on success, non-zero return value from `notify_cb`, or error
|
||||
* code < 0 (use giterr_last for error details)
|
||||
*/
|
||||
GIT_EXTERN(int) git_checkout_tree(
|
||||
git_repository *repo,
|
||||
|
||||
@ -26,23 +26,25 @@ GIT_BEGIN_DECL
|
||||
/**
|
||||
* Clone options structure
|
||||
*
|
||||
* Use zeros to indicate default settings. It's easiest to use the
|
||||
* `GIT_CLONE_OPTIONS_INIT` macro:
|
||||
* Use the GIT_CLONE_OPTIONS_INIT to get the default settings, like this:
|
||||
*
|
||||
* git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
|
||||
*
|
||||
* - `checkout_opts` is options for the checkout step. To disable checkout,
|
||||
* set the `checkout_strategy` to GIT_CHECKOUT_DEFAULT.
|
||||
* - `bare` should be set to zero to create a standard repo, non-zero for
|
||||
* a bare repo
|
||||
* - `ignore_cert_errors` should be set to 1 if errors validating the remote host's
|
||||
* certificate should be ignored.
|
||||
* - `checkout_opts` are option passed to the checkout step. To disable
|
||||
* checkout, set the `checkout_strategy` to GIT_CHECKOUT_NONE.
|
||||
* Generally you will want the use GIT_CHECKOUT_SAFE_CREATE to create
|
||||
* all files in the working directory for the newly cloned repository.
|
||||
* - `bare` should be set to zero (false) to create a standard repo,
|
||||
* or non-zero for a bare repo
|
||||
* - `ignore_cert_errors` should be set to 1 if errors validating the
|
||||
* remote host's certificate should be ignored.
|
||||
*
|
||||
* ** "origin" remote options: **
|
||||
* - `remote_name` is the name given to the "origin" remote. The default is
|
||||
* "origin".
|
||||
* - `checkout_branch` gives the name of the branch to checkout. NULL means
|
||||
* use the remote's HEAD.
|
||||
*
|
||||
* - `remote_name` is the name to be given to the "origin" remote. The
|
||||
* default is "origin".
|
||||
* - `checkout_branch` gives the name of the branch to checkout. NULL
|
||||
* means use the remote's HEAD.
|
||||
*/
|
||||
|
||||
typedef struct git_clone_options {
|
||||
@ -70,16 +72,17 @@ typedef struct git_clone_options {
|
||||
* @param out pointer that will receive the resulting repository object
|
||||
* @param url the remote repository to clone
|
||||
* @param local_path local directory to clone to
|
||||
* @param options configuration options for the clone. If NULL, the function
|
||||
* works as though GIT_OPTIONS_INIT were passed.
|
||||
* @return 0 on success, GIT_ERROR otherwise (use giterr_last for information
|
||||
* about the error)
|
||||
* @param options configuration options for the clone. If NULL, the
|
||||
* function works as though GIT_OPTIONS_INIT were passed.
|
||||
* @return 0 on success, any non-zero return value from a callback
|
||||
* function, or a negative value to indicate an error (use
|
||||
* `giterr_last` for a detailed error message)
|
||||
*/
|
||||
GIT_EXTERN(int) git_clone(
|
||||
git_repository **out,
|
||||
const char *url,
|
||||
const char *local_path,
|
||||
const git_clone_options *options);
|
||||
git_repository **out,
|
||||
const char *url,
|
||||
const char *local_path,
|
||||
const git_clone_options *options);
|
||||
|
||||
/**
|
||||
* Clone into a repository
|
||||
@ -91,11 +94,17 @@ GIT_EXTERN(int) git_clone(
|
||||
* @param repo the repository to use
|
||||
* @param remote the remote repository to clone from
|
||||
* @param co_opts options to use during checkout
|
||||
* @param branch the branch to checkout after the clone, pass NULL for the remote's
|
||||
* default branch
|
||||
* @return 0 on success or an error code
|
||||
* @param branch the branch to checkout after the clone, pass NULL for the
|
||||
* remote's default branch
|
||||
* @return 0 on success, any non-zero return value from a callback
|
||||
* function, or a negative value to indicate an error (use
|
||||
* `giterr_last` for a detailed error message)
|
||||
*/
|
||||
GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch);
|
||||
GIT_EXTERN(int) git_clone_into(
|
||||
git_repository *repo,
|
||||
git_remote *remote,
|
||||
const git_checkout_opts *co_opts,
|
||||
const char *branch);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
@ -450,13 +450,13 @@ GIT_EXTERN(int) git_config_delete_multivar(git_config *cfg, const char *name, co
|
||||
*
|
||||
* 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 stops iterating and returns `GIT_EUSER`.
|
||||
* If the callback returns a non-zero value, the function stops iterating
|
||||
* and returns that value to the caller.
|
||||
*
|
||||
* @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 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_foreach(
|
||||
const git_config *cfg,
|
||||
@ -612,8 +612,8 @@ GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value);
|
||||
GIT_EXTERN(int) git_config_backend_foreach_match(
|
||||
git_config_backend *backend,
|
||||
const char *regexp,
|
||||
int (*fn)(const git_config_entry *, void *),
|
||||
void *data);
|
||||
git_config_foreach_cb callback,
|
||||
void *payload);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -468,7 +468,7 @@ typedef int (*git_diff_line_cb)(
|
||||
* Flags to control the behavior of diff rename/copy detection.
|
||||
*/
|
||||
typedef enum {
|
||||
/** Obey `diff.renames`. This is overridden by any other GIT_DIFF_FIND_ALL flag. */
|
||||
/** Obey `diff.renames`. Overridden by any other GIT_DIFF_FIND_... flag. */
|
||||
GIT_DIFF_FIND_BY_CONFIG = 0,
|
||||
|
||||
/** Look for renames? (`--find-renames`) */
|
||||
@ -577,9 +577,9 @@ typedef struct {
|
||||
unsigned int version;
|
||||
|
||||
/**
|
||||
* Combination of git_diff_find_t values (default FIND_BY_CONFIG).
|
||||
* Note that if you don't explicitly set this, `diff.renames` could be set
|
||||
* to false, resulting in `git_diff_find_similar` doing nothing.
|
||||
* Combination of git_diff_find_t values (default GIT_DIFF_FIND_BY_CONFIG).
|
||||
* NOTE: if you don't explicitly set this, `diff.renames` could be set
|
||||
* to false, resulting in `git_diff_find_similar` doing nothing.
|
||||
*/
|
||||
uint32_t flags;
|
||||
|
||||
@ -870,7 +870,7 @@ GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff);
|
||||
* 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`.
|
||||
* the iteration and return the value to the user.
|
||||
*
|
||||
* @param diff A git_diff generated by one of the above functions.
|
||||
* @param file_cb Callback function to make per file in the diff.
|
||||
@ -881,7 +881,7 @@ GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff);
|
||||
* same callback will be made for context lines, added, and
|
||||
* removed lines, and even for a deleted trailing newline.
|
||||
* @param payload Reference pointer that will be passed to your callbacks.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_foreach(
|
||||
git_diff *diff,
|
||||
@ -918,13 +918,13 @@ typedef enum {
|
||||
* Iterate over a diff generating formatted text output.
|
||||
*
|
||||
* Returning a non-zero value from the callbacks will terminate the
|
||||
* iteration and cause this return `GIT_EUSER`.
|
||||
* iteration and return the non-zero value to the caller.
|
||||
*
|
||||
* @param diff A git_diff generated by one of the above functions.
|
||||
* @param format A git_diff_format_t value to pick the text format.
|
||||
* @param print_cb Callback to make per line of diff text.
|
||||
* @param payload Reference pointer that will be passed to your callback.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_print(
|
||||
git_diff *diff,
|
||||
@ -964,7 +964,7 @@ GIT_EXTERN(int) git_diff_print(
|
||||
* @param hunk_cb Callback for each hunk in diff; can be NULL
|
||||
* @param line_cb Callback for each line in diff; can be NULL
|
||||
* @param payload Payload passed to each callback function
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback return, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_blobs(
|
||||
const git_blob *old_blob,
|
||||
@ -999,7 +999,7 @@ GIT_EXTERN(int) git_diff_blobs(
|
||||
* @param hunk_cb Callback for each hunk in diff; can be NULL
|
||||
* @param line_cb Callback for each line in diff; can be NULL
|
||||
* @param payload Payload passed to each callback function
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback return, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_diff_blob_to_buffer(
|
||||
const git_blob *old_blob,
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#define INCLUDE_git_errors_h__
|
||||
|
||||
#include "common.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/**
|
||||
* @file git2/errors.h
|
||||
@ -20,25 +19,38 @@ GIT_BEGIN_DECL
|
||||
|
||||
/** Generic return codes */
|
||||
typedef enum {
|
||||
GIT_OK = 0,
|
||||
GIT_ERROR = -1,
|
||||
GIT_ENOTFOUND = -3,
|
||||
GIT_EEXISTS = -4,
|
||||
GIT_EAMBIGUOUS = -5,
|
||||
GIT_EBUFS = -6,
|
||||
GIT_EUSER = -7,
|
||||
GIT_EBAREREPO = -8,
|
||||
GIT_EUNBORNBRANCH = -9,
|
||||
GIT_EUNMERGED = -10,
|
||||
GIT_ENONFASTFORWARD = -11,
|
||||
GIT_EINVALIDSPEC = -12,
|
||||
GIT_EMERGECONFLICT = -13,
|
||||
GIT_ELOCKED = -14,
|
||||
GIT_OK = 0, /*< No error */
|
||||
|
||||
GIT_PASSTHROUGH = -30,
|
||||
GIT_ITEROVER = -31,
|
||||
GIT_ERROR = -1, /*< Generic error */
|
||||
GIT_ENOTFOUND = -3, /*< Requested object could not be found */
|
||||
GIT_EEXISTS = -4, /*< Object exists preventing operation */
|
||||
GIT_EAMBIGUOUS = -5, /*< More than one object matches */
|
||||
GIT_EBUFS = -6, /*< Output buffer too short to hold data */
|
||||
|
||||
/* GIT_EUSER is a special error that is never generated by libgit2
|
||||
* code. You can return it from a callback (e.g to stop an iteration)
|
||||
* to know that it was generated by the callback and not by libgit2.
|
||||
*/
|
||||
GIT_EUSER = -7,
|
||||
|
||||
GIT_EBAREREPO = -8, /*< Operation not allowed on bare repository */
|
||||
GIT_EUNBORNBRANCH = -9, /*< HEAD refers to branch with no commits */
|
||||
GIT_EUNMERGED = -10, /*< Merge in progress prevented operation */
|
||||
GIT_ENONFASTFORWARD = -11, /*< Reference was not fast-forwardable */
|
||||
GIT_EINVALIDSPEC = -12, /*< Name/ref spec was not in a valid format */
|
||||
GIT_EMERGECONFLICT = -13, /*< Merge conflicts prevented operation */
|
||||
GIT_ELOCKED = -14, /*< Lock file prevented operation */
|
||||
|
||||
GIT_PASSTHROUGH = -30, /*< Internal only */
|
||||
GIT_ITEROVER = -31, /*< Signals end of iteration with iterator */
|
||||
} git_error_code;
|
||||
|
||||
/**
|
||||
* Structure to store extra details of the last error that occurred.
|
||||
*
|
||||
* This is kept on a per-thread basis if GIT_THREADS was defined when the
|
||||
* library was build, otherwise one is kept globally for the library
|
||||
*/
|
||||
typedef struct {
|
||||
char *message;
|
||||
int klass;
|
||||
@ -72,6 +84,7 @@ typedef enum {
|
||||
GITERR_SSH,
|
||||
GITERR_FILTER,
|
||||
GITERR_REVERT,
|
||||
GITERR_CALLBACK,
|
||||
} git_error_t;
|
||||
|
||||
/**
|
||||
@ -91,7 +104,7 @@ GIT_EXTERN(void) giterr_clear(void);
|
||||
* Get the last error data and clear it.
|
||||
*
|
||||
* This copies the last error into the given `git_error` struct
|
||||
* and returns 0 if the copy was successful, leaving the error
|
||||
* and returns 0 if the copy was successful, leaving the error
|
||||
* cleared as if `giterr_clear` had been called.
|
||||
*
|
||||
* If there was no existing error in the library, -1 will be returned
|
||||
|
||||
@ -493,7 +493,7 @@ GIT_EXTERN(int) git_index_remove_bypath(git_index *index, const char *path);
|
||||
* item in the working directory immediately *before* it is added to /
|
||||
* updated in the index. Returning zero will add the item to the index,
|
||||
* greater than zero will skip the item, and less than zero will abort the
|
||||
* scan and cause GIT_EUSER to be returned.
|
||||
* scan and return that value to the caller.
|
||||
*
|
||||
* @param index an existing index object
|
||||
* @param pathspec array of path patterns
|
||||
@ -502,7 +502,7 @@ GIT_EXTERN(int) git_index_remove_bypath(git_index *index, const char *path);
|
||||
* gets index of matching pathspec entry); can be NULL;
|
||||
* return 0 to add, >0 to skip, <0 to abort scan.
|
||||
* @param payload payload passed through to callback function
|
||||
* @return 0 or an error code
|
||||
* @return 0 on success, negative callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_index_add_all(
|
||||
git_index *index,
|
||||
@ -524,7 +524,7 @@ GIT_EXTERN(int) git_index_add_all(
|
||||
* gets index of matching pathspec entry); can be NULL;
|
||||
* return 0 to add, >0 to skip, <0 to abort scan.
|
||||
* @param payload payload passed through to callback function
|
||||
* @return 0 or an error code
|
||||
* @return 0 on success, negative callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_index_remove_all(
|
||||
git_index *index,
|
||||
@ -553,7 +553,7 @@ GIT_EXTERN(int) git_index_remove_all(
|
||||
* gets index of matching pathspec entry); can be NULL;
|
||||
* return 0 to add, >0 to skip, <0 to abort scan.
|
||||
* @param payload payload passed through to callback function
|
||||
* @return 0 or an error code
|
||||
* @return 0 on success, negative callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_index_update_all(
|
||||
git_index *index,
|
||||
|
||||
@ -189,7 +189,7 @@ GIT_EXTERN(int) git_note_default_ref(const char **out, git_repository *repo);
|
||||
*
|
||||
* @param payload Extra parameter to callback function.
|
||||
*
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_note_foreach(
|
||||
git_repository *repo,
|
||||
|
||||
@ -189,7 +189,7 @@ GIT_EXTERN(int) git_odb_refresh(struct git_odb *db);
|
||||
* @param db database to use
|
||||
* @param cb the callback to call for each object
|
||||
* @param payload data to pass to the callback
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_foreach(git_odb *db, git_odb_foreach_cb cb, void *payload);
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ typedef enum {
|
||||
GIT_PACKBUILDER_ADDING_OBJECTS = 0,
|
||||
GIT_PACKBUILDER_DELTAFICATION = 1,
|
||||
} git_packbuilder_stage_t;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a new packbuilder
|
||||
*
|
||||
@ -143,6 +143,7 @@ GIT_EXTERN(int) git_packbuilder_write(
|
||||
GIT_EXTERN(const git_oid *) git_packbuilder_hash(git_packbuilder *pb);
|
||||
|
||||
typedef int (*git_packbuilder_foreach_cb)(void *buf, size_t size, void *payload);
|
||||
|
||||
/**
|
||||
* Create the new pack and pass each object to the callback
|
||||
*
|
||||
|
||||
@ -218,13 +218,13 @@ GIT_EXTERN(size_t) git_patch_size(
|
||||
* Serialize the patch to text via callback.
|
||||
*
|
||||
* Returning a non-zero value from the callback will terminate the iteration
|
||||
* and cause this return `GIT_EUSER`.
|
||||
* and return that value to the caller.
|
||||
*
|
||||
* @param patch A git_patch representing changes to one file
|
||||
* @param print_cb Callback function to output lines of the patch. Will be
|
||||
* called for file headers, hunk headers, and diff lines.
|
||||
* @param payload Reference pointer that will be passed to your callbacks.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_patch_print(
|
||||
git_patch *patch,
|
||||
|
||||
@ -132,17 +132,19 @@ GIT_EXTERN(int) git_push_finish(git_push *push);
|
||||
GIT_EXTERN(int) git_push_unpack_ok(git_push *push);
|
||||
|
||||
/**
|
||||
* Call callback `cb' on each status
|
||||
* Invoke callback `cb' on each status entry
|
||||
*
|
||||
* For each of the updated references, we receive a status report in the
|
||||
* form of `ok refs/heads/master` or `ng refs/heads/master <msg>`.
|
||||
* `msg != NULL` means the reference has not been updated for the given
|
||||
* reason.
|
||||
*
|
||||
* Return a non-zero value from the callback to stop the loop.
|
||||
*
|
||||
* @param push The push object
|
||||
* @param cb The callback to call on each object
|
||||
*
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_push_status_foreach(git_push *push,
|
||||
int (*cb)(const char *ref, const char *msg, void *data),
|
||||
|
||||
@ -310,20 +310,33 @@ typedef int (*git_reference_foreach_name_cb)(const char *name, void *payload);
|
||||
* Perform a callback on each reference in the repository.
|
||||
*
|
||||
* The `callback` function will be called for each reference in the
|
||||
* repository, receiving the name of the reference and the `payload` value
|
||||
* repository, receiving the reference object and 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 callback Function which will be called for every listed ref
|
||||
* @param payload Additional data to pass to the callback
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_foreach(
|
||||
git_repository *repo,
|
||||
git_reference_foreach_cb callback,
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* Perform a callback on the fully-qualified name of each reference.
|
||||
*
|
||||
* The `callback` function will be called for each reference in the
|
||||
* repository, receiving the name of the reference and 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 callback Function which will be called for every listed ref name
|
||||
* @param payload Additional data to pass to the callback
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_foreach_name(
|
||||
git_repository *repo,
|
||||
git_reference_foreach_name_cb callback,
|
||||
|
||||
@ -503,14 +503,18 @@ typedef int (*git_repository_fetchhead_foreach_cb)(const char *ref_name,
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* Call callback 'callback' for each entry in the given FETCH_HEAD file.
|
||||
* Invoke 'callback' for each entry in the given FETCH_HEAD file.
|
||||
*
|
||||
* Return a non-zero value from the callback to stop the loop.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param callback Callback function
|
||||
* @param payload Pointer to callback data (optional)
|
||||
* @return 0 on success, GIT_ENOTFOUND, GIT_EUSER or error
|
||||
* @return 0 on success, non-zero callback return value, GIT_ENOTFOUND if
|
||||
* there is no FETCH_HEAD file, or other error code.
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_fetchhead_foreach(git_repository *repo,
|
||||
GIT_EXTERN(int) git_repository_fetchhead_foreach(
|
||||
git_repository *repo,
|
||||
git_repository_fetchhead_foreach_cb callback,
|
||||
void *payload);
|
||||
|
||||
@ -518,15 +522,19 @@ typedef int (*git_repository_mergehead_foreach_cb)(const git_oid *oid,
|
||||
void *payload);
|
||||
|
||||
/**
|
||||
* If a merge is in progress, call callback 'cb' for each commit ID in the
|
||||
* If a merge is in progress, invoke 'callback' for each commit ID in the
|
||||
* MERGE_HEAD file.
|
||||
*
|
||||
* Return a non-zero value from the callback to stop the loop.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param callback Callback function
|
||||
* @param payload Pointer to callback data (optional)
|
||||
* @return 0 on success, GIT_ENOTFOUND, GIT_EUSER or error
|
||||
* @return 0 on success, non-zero callback return value, GIT_ENOTFOUND if
|
||||
* there is no MERGE_HEAD file, or other error code.
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo,
|
||||
GIT_EXTERN(int) git_repository_mergehead_foreach(
|
||||
git_repository *repo,
|
||||
git_repository_mergehead_foreach_cb callback,
|
||||
void *payload);
|
||||
|
||||
|
||||
@ -62,19 +62,15 @@ GIT_EXTERN(int) git_stash_save(
|
||||
unsigned int flags);
|
||||
|
||||
/**
|
||||
* When iterating over all the stashed states, callback that will be
|
||||
* issued per entry.
|
||||
* This is a callback function you can provide to iterate over all the
|
||||
* stashed states that will be invoked per entry.
|
||||
*
|
||||
* @param index The position within the stash list. 0 points to the
|
||||
* most recent stashed state.
|
||||
*
|
||||
* most recent stashed state.
|
||||
* @param message The stash message.
|
||||
*
|
||||
* @param stash_id The commit oid of the stashed state.
|
||||
*
|
||||
* @param payload Extra parameter to callback function.
|
||||
*
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 to continue iterating or non-zero to stop
|
||||
*/
|
||||
typedef int (*git_stash_cb)(
|
||||
size_t index,
|
||||
@ -89,12 +85,12 @@ typedef int (*git_stash_cb)(
|
||||
*
|
||||
* @param repo Repository where to find the stash.
|
||||
*
|
||||
* @param callback Callback to invoke per found stashed state. The most recent
|
||||
* stash state will be enumerated first.
|
||||
* @param callback Callback to invoke per found stashed state. The most
|
||||
* recent stash state will be enumerated first.
|
||||
*
|
||||
* @param payload Extra parameter to callback function.
|
||||
*
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_stash_foreach(
|
||||
git_repository *repo,
|
||||
|
||||
@ -203,12 +203,12 @@ typedef struct {
|
||||
* into this function.
|
||||
*
|
||||
* If the callback returns a non-zero value, this function will stop looping
|
||||
* and return GIT_EUSER.
|
||||
* and return that value to caller.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param callback The function to call on each file
|
||||
* @param payload Pointer to pass through to callback function
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_status_foreach(
|
||||
git_repository *repo,
|
||||
@ -227,7 +227,7 @@ GIT_EXTERN(int) git_status_foreach(
|
||||
* @param opts Status options structure
|
||||
* @param callback The function to call on each file
|
||||
* @param payload Pointer to pass through to callback function
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success, non-zero callback return value, or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_status_foreach_ext(
|
||||
git_repository *repo,
|
||||
|
||||
@ -149,6 +149,7 @@ typedef int (*git_filter_init_fn)(git_filter *self);
|
||||
* Specified as `filter.shutdown`, this is an optional callback invoked
|
||||
* when the filter is unregistered or when libgit2 is shutting down. It
|
||||
* will be called once at most and should release resources as needed.
|
||||
* This may be called even if the `initialize` callback was not made.
|
||||
*
|
||||
* Typically this function will free the `git_filter` object itself.
|
||||
*/
|
||||
|
||||
@ -332,11 +332,18 @@ GIT_EXTERN(int) git_treebuilder_insert(
|
||||
GIT_EXTERN(int) git_treebuilder_remove(
|
||||
git_treebuilder *bld, const char *filename);
|
||||
|
||||
/**
|
||||
* Callback for git_treebuilder_filter
|
||||
*
|
||||
* The return value is treated as a boolean, with zero indicating that the
|
||||
* entry should be left alone and any non-zero value meaning that the
|
||||
* entry should be removed from the treebuilder list (i.e. filtered out).
|
||||
*/
|
||||
typedef int (*git_treebuilder_filter_cb)(
|
||||
const git_tree_entry *entry, void *payload);
|
||||
|
||||
/**
|
||||
* Filter the entries in the tree
|
||||
* Selectively remove entries in the tree
|
||||
*
|
||||
* The `filter` callback will be called for each entry in the tree with a
|
||||
* pointer to the entry and the provided `payload`; if the callback returns
|
||||
@ -344,7 +351,7 @@ typedef int (*git_treebuilder_filter_cb)(
|
||||
*
|
||||
* @param bld Tree builder
|
||||
* @param filter Callback to filter entries
|
||||
* @param payload Extra data to pass to filter
|
||||
* @param payload Extra data to pass to filter callback
|
||||
*/
|
||||
GIT_EXTERN(void) git_treebuilder_filter(
|
||||
git_treebuilder *bld,
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#include <git2/common.h>
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
|
||||
#include "posix.h"
|
||||
#include "map.h"
|
||||
#include <errno.h>
|
||||
|
||||
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
|
||||
{
|
||||
GIT_MMAP_VALIDATE(out, len, prot, flags);
|
||||
|
||||
out->data = NULL;
|
||||
out->len = 0;
|
||||
|
||||
if ((prot & GIT_PROT_WRITE) && ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)) {
|
||||
giterr_set(GITERR_OS, "Trying to map shared-writeable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
out->data = malloc(len);
|
||||
GITERR_CHECK_ALLOC(out->data);
|
||||
|
||||
if ((p_lseek(fd, offset, SEEK_SET) < 0) || ((size_t)p_read(fd, out->data, len) != len)) {
|
||||
giterr_set(GITERR_OS, "mmap emulation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
out->len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int p_munmap(git_map *map)
|
||||
{
|
||||
assert(map != NULL);
|
||||
free(map->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
21
src/attr.c
21
src/attr.c
@ -193,8 +193,7 @@ int git_attr_foreach(
|
||||
|
||||
error = callback(assign->name, assign->value, payload);
|
||||
if (error) {
|
||||
giterr_clear();
|
||||
error = GIT_EUSER;
|
||||
giterr_set_after_callback(error);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
@ -536,7 +535,7 @@ static int collect_attr_files(
|
||||
int error;
|
||||
git_buf dir = GIT_BUF_INIT;
|
||||
const char *workdir = git_repository_workdir(repo);
|
||||
attr_walk_up_info info;
|
||||
attr_walk_up_info info = { NULL };
|
||||
|
||||
if (git_attr_cache__init(repo) < 0 ||
|
||||
git_vector_init(files, 4, NULL) < 0)
|
||||
@ -603,11 +602,15 @@ static int attr_cache__lookup_path(
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
int error;
|
||||
const char *cfgval = NULL;
|
||||
const git_config_entry *entry = NULL;
|
||||
|
||||
*out = NULL;
|
||||
|
||||
if (!(error = git_config_get_string(&cfgval, cfg, key))) {
|
||||
if ((error = git_config__lookup_entry(&entry, cfg, key, false)) < 0)
|
||||
return error;
|
||||
|
||||
if (entry) {
|
||||
const char *cfgval = entry->value;
|
||||
|
||||
/* expand leading ~/ as needed */
|
||||
if (cfgval && cfgval[0] == '~' && cfgval[1] == '/' &&
|
||||
@ -616,13 +619,9 @@ static int attr_cache__lookup_path(
|
||||
else if (cfgval)
|
||||
*out = git__strdup(cfgval);
|
||||
|
||||
} else if (error == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
|
||||
if (!git_futils_find_xdg_file(&buf, fallback))
|
||||
*out = git_buf_detach(&buf);
|
||||
}
|
||||
else if (!git_futils_find_xdg_file(&buf, fallback))
|
||||
*out = git_buf_detach(&buf);
|
||||
|
||||
git_buf_free(&buf);
|
||||
|
||||
|
||||
29
src/blame.c
29
src/blame.c
@ -108,17 +108,23 @@ git_blame* git_blame__alloc(
|
||||
git_blame_options opts,
|
||||
const char *path)
|
||||
{
|
||||
git_blame *gbr = (git_blame*)git__calloc(1, sizeof(git_blame));
|
||||
if (!gbr) {
|
||||
giterr_set_oom();
|
||||
git_blame *gbr = git__calloc(1, sizeof(git_blame));
|
||||
if (!gbr)
|
||||
return NULL;
|
||||
}
|
||||
git_vector_init(&gbr->hunks, 8, hunk_cmp);
|
||||
git_vector_init(&gbr->paths, 8, paths_cmp);
|
||||
|
||||
gbr->repository = repo;
|
||||
gbr->options = opts;
|
||||
gbr->path = git__strdup(path);
|
||||
git_vector_insert(&gbr->paths, git__strdup(path));
|
||||
|
||||
if (git_vector_init(&gbr->hunks, 8, hunk_cmp) < 0 ||
|
||||
git_vector_init(&gbr->paths, 8, paths_cmp) < 0 ||
|
||||
(gbr->path = git__strdup(path)) == NULL ||
|
||||
git_vector_insert(&gbr->paths, git__strdup(path)) < 0)
|
||||
{
|
||||
git_blame_free(gbr);
|
||||
git__free(gbr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gbr;
|
||||
}
|
||||
|
||||
@ -126,7 +132,6 @@ void git_blame_free(git_blame *blame)
|
||||
{
|
||||
size_t i;
|
||||
git_blame_hunk *hunk;
|
||||
char *path;
|
||||
|
||||
if (!blame) return;
|
||||
|
||||
@ -134,13 +139,11 @@ void git_blame_free(git_blame *blame)
|
||||
free_hunk(hunk);
|
||||
git_vector_free(&blame->hunks);
|
||||
|
||||
git_vector_foreach(&blame->paths, i, path)
|
||||
git__free(path);
|
||||
git_vector_free(&blame->paths);
|
||||
git_vector_free_deep(&blame->paths);
|
||||
|
||||
git_array_clear(blame->line_index);
|
||||
|
||||
git__free((void*)blame->path);
|
||||
git__free(blame->path);
|
||||
git_blob_free(blame->final_blob);
|
||||
git__free(blame);
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ typedef struct git_blame__entry {
|
||||
} git_blame__entry;
|
||||
|
||||
struct git_blame {
|
||||
const char *path;
|
||||
char *path;
|
||||
git_repository *repository;
|
||||
git_blame_options options;
|
||||
|
||||
|
||||
34
src/blob.c
34
src/blob.c
@ -272,37 +272,44 @@ int git_blob_create_fromchunks(
|
||||
int (*source_cb)(char *content, size_t max_length, void *payload),
|
||||
void *payload)
|
||||
{
|
||||
int error = -1, read_bytes;
|
||||
int error;
|
||||
char *content = NULL;
|
||||
git_filebuf file = GIT_FILEBUF_INIT;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
if (git_buf_joinpath(
|
||||
&path, git_repository_path(repo), GIT_OBJECTS_DIR "streamed") < 0)
|
||||
assert(oid && repo && source_cb);
|
||||
|
||||
if ((error = git_buf_joinpath(
|
||||
&path, git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0)
|
||||
goto cleanup;
|
||||
|
||||
content = git__malloc(BUFFER_SIZE);
|
||||
GITERR_CHECK_ALLOC(content);
|
||||
|
||||
if (git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY, 0666) < 0)
|
||||
if ((error = git_filebuf_open(
|
||||
&file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY, 0666)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
while (1) {
|
||||
read_bytes = source_cb(content, BUFFER_SIZE, payload);
|
||||
int read_bytes = source_cb(content, BUFFER_SIZE, payload);
|
||||
|
||||
assert(read_bytes <= BUFFER_SIZE);
|
||||
|
||||
if (read_bytes <= 0)
|
||||
if (!read_bytes)
|
||||
break;
|
||||
|
||||
if (git_filebuf_write(&file, content, read_bytes) < 0)
|
||||
if (read_bytes > BUFFER_SIZE) {
|
||||
giterr_set(GITERR_OBJECT, "Invalid chunk size while creating blob");
|
||||
error = GIT_EBUFS;
|
||||
} else if (read_bytes < 0) {
|
||||
error = giterr_set_after_callback(read_bytes);
|
||||
} else {
|
||||
error = git_filebuf_write(&file, content, read_bytes);
|
||||
}
|
||||
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (read_bytes < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_filebuf_flush(&file) < 0)
|
||||
if ((error = git_filebuf_flush(&file)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
error = git_blob__create_from_paths(
|
||||
@ -312,6 +319,7 @@ cleanup:
|
||||
git_buf_free(&path);
|
||||
git_filebuf_cleanup(&file);
|
||||
git__free(content);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
41
src/branch.c
41
src/branch.c
@ -90,29 +90,28 @@ int git_branch_delete(git_reference *branch)
|
||||
|
||||
assert(branch);
|
||||
|
||||
if (!git_reference_is_branch(branch) &&
|
||||
!git_reference_is_remote(branch)) {
|
||||
giterr_set(GITERR_INVALID, "Reference '%s' is not a valid branch.", git_reference_name(branch));
|
||||
return -1;
|
||||
if (!git_reference_is_branch(branch) && !git_reference_is_remote(branch)) {
|
||||
giterr_set(GITERR_INVALID, "Reference '%s' is not a valid branch.",
|
||||
git_reference_name(branch));
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
if ((is_head = git_branch_is_head(branch)) < 0)
|
||||
return is_head;
|
||||
|
||||
if (is_head) {
|
||||
giterr_set(GITERR_REFERENCE,
|
||||
"Cannot delete branch '%s' as it is the current HEAD of the repository.", git_reference_name(branch));
|
||||
giterr_set(GITERR_REFERENCE, "Cannot delete branch '%s' as it is "
|
||||
"the current HEAD of the repository.", git_reference_name(branch));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (git_buf_printf(&config_section, "branch.%s", git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
|
||||
if (git_buf_join(&config_section, '.', "branch",
|
||||
git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0)
|
||||
goto on_error;
|
||||
|
||||
if (git_config_rename_section(
|
||||
git_reference_owner(branch),
|
||||
git_buf_cstr(&config_section),
|
||||
NULL) < 0)
|
||||
goto on_error;
|
||||
git_reference_owner(branch), git_buf_cstr(&config_section), NULL) < 0)
|
||||
goto on_error;
|
||||
|
||||
if (git_reference_delete(branch) < 0)
|
||||
goto on_error;
|
||||
@ -206,17 +205,21 @@ int git_branch_move(
|
||||
if (error < 0)
|
||||
goto done;
|
||||
|
||||
git_buf_printf(&old_config_section,
|
||||
"branch.%s", git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR));
|
||||
/* first update ref then config so failure won't trash config */
|
||||
|
||||
git_buf_printf(&new_config_section, "branch.%s", new_branch_name);
|
||||
|
||||
if ((error = git_config_rename_section(git_reference_owner(branch),
|
||||
git_buf_cstr(&old_config_section),
|
||||
git_buf_cstr(&new_config_section))) < 0)
|
||||
error = git_reference_rename(
|
||||
out, branch, git_buf_cstr(&new_reference_name), force);
|
||||
if (error < 0)
|
||||
goto done;
|
||||
|
||||
error = git_reference_rename(out, branch, git_buf_cstr(&new_reference_name), force);
|
||||
git_buf_join(&old_config_section, '.', "branch",
|
||||
git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR));
|
||||
git_buf_join(&new_config_section, '.', "branch", new_branch_name);
|
||||
|
||||
error = git_config_rename_section(
|
||||
git_reference_owner(branch),
|
||||
git_buf_cstr(&old_config_section),
|
||||
git_buf_cstr(&new_config_section));
|
||||
|
||||
done:
|
||||
git_buf_free(&new_reference_name);
|
||||
|
||||
262
src/checkout.c
262
src/checkout.c
@ -83,10 +83,8 @@ static int checkout_notify(
|
||||
const git_diff_file *baseline = NULL, *target = NULL, *workdir = NULL;
|
||||
const char *path = NULL;
|
||||
|
||||
if (!data->opts.notify_cb)
|
||||
return 0;
|
||||
|
||||
if ((why & data->opts.notify_flags) == 0)
|
||||
if (!data->opts.notify_cb ||
|
||||
(why & data->opts.notify_flags) == 0)
|
||||
return 0;
|
||||
|
||||
if (wditem) {
|
||||
@ -125,8 +123,13 @@ static int checkout_notify(
|
||||
path = delta->old_file.path;
|
||||
}
|
||||
|
||||
return data->opts.notify_cb(
|
||||
why, path, baseline, target, workdir, data->opts.notify_payload);
|
||||
{
|
||||
int error = data->opts.notify_cb(
|
||||
why, path, baseline, target, workdir, data->opts.notify_payload);
|
||||
|
||||
return giterr_set_after_callback_function(
|
||||
error, "git_checkout notification");
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkout_is_workdir_modified(
|
||||
@ -186,69 +189,66 @@ static bool checkout_is_workdir_modified(
|
||||
((data->strategy & GIT_CHECKOUT_##FLAG) ? CHECKOUT_ACTION__##YES : CHECKOUT_ACTION__##NO)
|
||||
|
||||
static int checkout_action_common(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
int action,
|
||||
const git_diff_delta *delta,
|
||||
const git_index_entry *wd)
|
||||
{
|
||||
git_checkout_notify_t notify = GIT_CHECKOUT_NOTIFY_NONE;
|
||||
|
||||
if (action <= 0)
|
||||
return action;
|
||||
|
||||
if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0)
|
||||
action = (action & ~CHECKOUT_ACTION__REMOVE);
|
||||
*action = (*action & ~CHECKOUT_ACTION__REMOVE);
|
||||
|
||||
if ((action & CHECKOUT_ACTION__UPDATE_BLOB) != 0) {
|
||||
if ((*action & CHECKOUT_ACTION__UPDATE_BLOB) != 0) {
|
||||
if (S_ISGITLINK(delta->new_file.mode))
|
||||
action = (action & ~CHECKOUT_ACTION__UPDATE_BLOB) |
|
||||
*action = (*action & ~CHECKOUT_ACTION__UPDATE_BLOB) |
|
||||
CHECKOUT_ACTION__UPDATE_SUBMODULE;
|
||||
|
||||
/* to "update" a symlink, we must remove the old one first */
|
||||
if (delta->new_file.mode == GIT_FILEMODE_LINK && wd != NULL)
|
||||
action |= CHECKOUT_ACTION__REMOVE;
|
||||
*action |= CHECKOUT_ACTION__REMOVE;
|
||||
|
||||
notify = GIT_CHECKOUT_NOTIFY_UPDATED;
|
||||
}
|
||||
|
||||
if ((action & CHECKOUT_ACTION__CONFLICT) != 0)
|
||||
if ((*action & CHECKOUT_ACTION__CONFLICT) != 0)
|
||||
notify = GIT_CHECKOUT_NOTIFY_CONFLICT;
|
||||
|
||||
if (notify != GIT_CHECKOUT_NOTIFY_NONE &&
|
||||
checkout_notify(data, notify, delta, wd) != 0)
|
||||
return GIT_EUSER;
|
||||
|
||||
return action;
|
||||
return checkout_notify(data, notify, delta, wd);
|
||||
}
|
||||
|
||||
static int checkout_action_no_wd(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
const git_diff_delta *delta)
|
||||
{
|
||||
int action = CHECKOUT_ACTION__NONE;
|
||||
int error = 0;
|
||||
|
||||
*action = CHECKOUT_ACTION__NONE;
|
||||
|
||||
switch (delta->status) {
|
||||
case GIT_DELTA_UNMODIFIED: /* case 12 */
|
||||
if (checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL))
|
||||
return GIT_EUSER;
|
||||
action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, NONE);
|
||||
error = checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
*action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, NONE);
|
||||
break;
|
||||
case GIT_DELTA_ADDED: /* case 2 or 28 (and 5 but not really) */
|
||||
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
break;
|
||||
case GIT_DELTA_MODIFIED: /* case 13 (and 35 but not really) */
|
||||
action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(SAFE_CREATE, UPDATE_BLOB, CONFLICT);
|
||||
break;
|
||||
case GIT_DELTA_TYPECHANGE: /* case 21 (B->T) and 28 (T->B)*/
|
||||
if (delta->new_file.mode == GIT_FILEMODE_TREE)
|
||||
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
break;
|
||||
case GIT_DELTA_DELETED: /* case 8 or 25 */
|
||||
default: /* impossible */
|
||||
break;
|
||||
}
|
||||
|
||||
return checkout_action_common(data, action, delta, NULL);
|
||||
return checkout_action_common(action, data, delta, NULL);
|
||||
}
|
||||
|
||||
static int checkout_action_wd_only(
|
||||
@ -257,6 +257,7 @@ static int checkout_action_wd_only(
|
||||
const git_index_entry *wd,
|
||||
git_vector *pathspec)
|
||||
{
|
||||
int error = 0;
|
||||
bool remove = false;
|
||||
git_checkout_notify_t notify = GIT_CHECKOUT_NOTIFY_NONE;
|
||||
|
||||
@ -269,13 +270,13 @@ static int checkout_action_wd_only(
|
||||
/* check if item is tracked in the index but not in the checkout diff */
|
||||
if (data->index != NULL) {
|
||||
if (wd->mode != GIT_FILEMODE_TREE) {
|
||||
int error;
|
||||
|
||||
if ((error = git_index_find(NULL, data->index, wd->path)) == 0) {
|
||||
if (!(error = git_index_find(NULL, data->index, wd->path))) {
|
||||
notify = GIT_CHECKOUT_NOTIFY_DIRTY;
|
||||
remove = ((data->strategy & GIT_CHECKOUT_FORCE) != 0);
|
||||
} else if (error != GIT_ENOTFOUND)
|
||||
return error;
|
||||
else
|
||||
giterr_clear();
|
||||
} else {
|
||||
/* for tree entries, we have to see if there are any index
|
||||
* entries that are contained inside that tree
|
||||
@ -301,18 +302,16 @@ static int checkout_action_wd_only(
|
||||
remove = ((data->strategy & GIT_CHECKOUT_REMOVE_UNTRACKED) != 0);
|
||||
}
|
||||
|
||||
if (checkout_notify(data, notify, NULL, wd))
|
||||
return GIT_EUSER;
|
||||
error = checkout_notify(data, notify, NULL, wd);
|
||||
|
||||
if (remove) {
|
||||
if (!error && remove) {
|
||||
char *path = git_pool_strdup(&data->pool, wd->path);
|
||||
GITERR_CHECK_ALLOC(path);
|
||||
|
||||
if (git_vector_insert(&data->removes, path) < 0)
|
||||
return -1;
|
||||
error = git_vector_insert(&data->removes, path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool submodule_is_config_only(
|
||||
@ -331,35 +330,35 @@ static bool submodule_is_config_only(
|
||||
}
|
||||
|
||||
static int checkout_action_with_wd(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
const git_diff_delta *delta,
|
||||
const git_index_entry *wd)
|
||||
{
|
||||
int action = CHECKOUT_ACTION__NONE;
|
||||
*action = CHECKOUT_ACTION__NONE;
|
||||
|
||||
switch (delta->status) {
|
||||
case GIT_DELTA_UNMODIFIED: /* case 14/15 or 33 */
|
||||
if (checkout_is_workdir_modified(data, &delta->old_file, wd)) {
|
||||
if (checkout_notify(
|
||||
data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd))
|
||||
return GIT_EUSER;
|
||||
action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, NONE);
|
||||
GITERR_CHECK_ERROR(
|
||||
checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd) );
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, NONE);
|
||||
}
|
||||
break;
|
||||
case GIT_DELTA_ADDED: /* case 3, 4 or 6 */
|
||||
action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
|
||||
break;
|
||||
case GIT_DELTA_DELETED: /* case 9 or 10 (or 26 but not really) */
|
||||
if (checkout_is_workdir_modified(data, &delta->old_file, wd))
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
|
||||
else
|
||||
action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE);
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE);
|
||||
break;
|
||||
case GIT_DELTA_MODIFIED: /* case 16, 17, 18 (or 36 but not really) */
|
||||
if (checkout_is_workdir_modified(data, &delta->old_file, wd))
|
||||
action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT);
|
||||
else
|
||||
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
break;
|
||||
case GIT_DELTA_TYPECHANGE: /* case 22, 23, 29, 30 */
|
||||
if (delta->old_file.mode == GIT_FILEMODE_TREE) {
|
||||
@ -367,92 +366,93 @@ static int checkout_action_with_wd(
|
||||
/* either deleting items in old tree will delete the wd dir,
|
||||
* or we'll get a conflict when we attempt blob update...
|
||||
*/
|
||||
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
else if (wd->mode == GIT_FILEMODE_COMMIT) {
|
||||
/* workdir is possibly a "phantom" submodule - treat as a
|
||||
* tree if the only submodule info came from the config
|
||||
*/
|
||||
if (submodule_is_config_only(data, wd->path))
|
||||
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
else
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
} else
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
|
||||
}
|
||||
else if (checkout_is_workdir_modified(data, &delta->old_file, wd))
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
else
|
||||
action = CHECKOUT_ACTION_IF(SAFE, REMOVE_AND_UPDATE, NONE);
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, REMOVE_AND_UPDATE, NONE);
|
||||
|
||||
/* don't update if the typechange is to a tree */
|
||||
if (delta->new_file.mode == GIT_FILEMODE_TREE)
|
||||
action = (action & ~CHECKOUT_ACTION__UPDATE_BLOB);
|
||||
*action = (*action & ~CHECKOUT_ACTION__UPDATE_BLOB);
|
||||
break;
|
||||
default: /* impossible */
|
||||
break;
|
||||
}
|
||||
|
||||
return checkout_action_common(data, action, delta, wd);
|
||||
return checkout_action_common(action, data, delta, wd);
|
||||
}
|
||||
|
||||
static int checkout_action_with_wd_blocker(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
const git_diff_delta *delta,
|
||||
const git_index_entry *wd)
|
||||
{
|
||||
int action = CHECKOUT_ACTION__NONE;
|
||||
*action = CHECKOUT_ACTION__NONE;
|
||||
|
||||
switch (delta->status) {
|
||||
case GIT_DELTA_UNMODIFIED:
|
||||
/* should show delta as dirty / deleted */
|
||||
if (checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd))
|
||||
return GIT_EUSER;
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, NONE);
|
||||
GITERR_CHECK_ERROR(
|
||||
checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd) );
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, NONE);
|
||||
break;
|
||||
case GIT_DELTA_ADDED:
|
||||
case GIT_DELTA_MODIFIED:
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
break;
|
||||
case GIT_DELTA_DELETED:
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT);
|
||||
break;
|
||||
case GIT_DELTA_TYPECHANGE:
|
||||
/* not 100% certain about this... */
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
break;
|
||||
default: /* impossible */
|
||||
break;
|
||||
}
|
||||
|
||||
return checkout_action_common(data, action, delta, wd);
|
||||
return checkout_action_common(action, data, delta, wd);
|
||||
}
|
||||
|
||||
static int checkout_action_with_wd_dir(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
const git_diff_delta *delta,
|
||||
const git_index_entry *wd)
|
||||
{
|
||||
int action = CHECKOUT_ACTION__NONE;
|
||||
*action = CHECKOUT_ACTION__NONE;
|
||||
|
||||
switch (delta->status) {
|
||||
case GIT_DELTA_UNMODIFIED: /* case 19 or 24 (or 34 but not really) */
|
||||
if (checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL) ||
|
||||
checkout_notify(
|
||||
data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd))
|
||||
return GIT_EUSER;
|
||||
GITERR_CHECK_ERROR(
|
||||
checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, NULL));
|
||||
GITERR_CHECK_ERROR(
|
||||
checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd));
|
||||
break;
|
||||
case GIT_DELTA_ADDED:/* case 4 (and 7 for dir) */
|
||||
case GIT_DELTA_MODIFIED: /* case 20 (or 37 but not really) */
|
||||
if (delta->old_file.mode == GIT_FILEMODE_COMMIT)
|
||||
/* expected submodule (and maybe found one) */;
|
||||
else if (delta->new_file.mode != GIT_FILEMODE_TREE)
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
break;
|
||||
case GIT_DELTA_DELETED: /* case 11 (and 27 for dir) */
|
||||
if (delta->old_file.mode != GIT_FILEMODE_TREE &&
|
||||
checkout_notify(
|
||||
data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd))
|
||||
return GIT_EUSER;
|
||||
if (delta->old_file.mode != GIT_FILEMODE_TREE)
|
||||
GITERR_CHECK_ERROR(
|
||||
checkout_notify(data, GIT_CHECKOUT_NOTIFY_UNTRACKED, NULL, wd));
|
||||
break;
|
||||
case GIT_DELTA_TYPECHANGE: /* case 24 or 31 */
|
||||
if (delta->old_file.mode == GIT_FILEMODE_TREE) {
|
||||
@ -462,39 +462,41 @@ static int checkout_action_with_wd_dir(
|
||||
* directory if is it left empty, so we can defer removing the
|
||||
* dir and it will succeed if no children are left.
|
||||
*/
|
||||
action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
if (action != CHECKOUT_ACTION__NONE)
|
||||
action |= CHECKOUT_ACTION__DEFER_REMOVE;
|
||||
*action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE);
|
||||
if (*action != CHECKOUT_ACTION__NONE)
|
||||
*action |= CHECKOUT_ACTION__DEFER_REMOVE;
|
||||
}
|
||||
else if (delta->new_file.mode != GIT_FILEMODE_TREE)
|
||||
/* For typechange to dir, dir is already created so no action */
|
||||
action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
*action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT);
|
||||
break;
|
||||
default: /* impossible */
|
||||
break;
|
||||
}
|
||||
|
||||
return checkout_action_common(data, action, delta, wd);
|
||||
return checkout_action_common(action, data, delta, wd);
|
||||
}
|
||||
|
||||
static int checkout_action(
|
||||
int *action,
|
||||
checkout_data *data,
|
||||
git_diff_delta *delta,
|
||||
git_iterator *workdir,
|
||||
const git_index_entry **wditem_ptr,
|
||||
const git_index_entry **wditem,
|
||||
git_vector *pathspec)
|
||||
{
|
||||
const git_index_entry *wd = *wditem_ptr;
|
||||
int cmp = -1, act;
|
||||
int cmp = -1, error;
|
||||
int (*strcomp)(const char *, const char *) = data->diff->strcomp;
|
||||
int (*pfxcomp)(const char *str, const char *pfx) = data->diff->pfxcomp;
|
||||
int error;
|
||||
int (*advance)(const git_index_entry **, git_iterator *) = NULL;
|
||||
|
||||
/* move workdir iterator to follow along with deltas */
|
||||
|
||||
while (1) {
|
||||
const git_index_entry *wd = *wditem;
|
||||
|
||||
if (!wd)
|
||||
return checkout_action_no_wd(data, delta);
|
||||
return checkout_action_no_wd(action, data, delta);
|
||||
|
||||
cmp = strcomp(wd->path, delta->old_file.path);
|
||||
|
||||
@ -512,79 +514,77 @@ static int checkout_action(
|
||||
if (cmp == 0) {
|
||||
if (wd->mode == GIT_FILEMODE_TREE) {
|
||||
/* case 2 - entry prefixed by workdir tree */
|
||||
error = git_iterator_advance_into_or_over(&wd, workdir);
|
||||
if (error && error != GIT_ITEROVER)
|
||||
goto fail;
|
||||
*wditem_ptr = wd;
|
||||
error = git_iterator_advance_into_or_over(wditem, workdir);
|
||||
if (error < 0 && error != GIT_ITEROVER)
|
||||
goto done;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* case 3 maybe - wd contains non-dir where dir expected */
|
||||
if (delta->old_file.path[strlen(wd->path)] == '/') {
|
||||
act = checkout_action_with_wd_blocker(data, delta, wd);
|
||||
*wditem_ptr =
|
||||
git_iterator_advance(&wd, workdir) ? NULL : wd;
|
||||
return act;
|
||||
error = checkout_action_with_wd_blocker(
|
||||
action, data, delta, wd);
|
||||
advance = git_iterator_advance;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* case 1 - handle wd item (if it matches pathspec) */
|
||||
if (checkout_action_wd_only(data, workdir, wd, pathspec) < 0)
|
||||
goto fail;
|
||||
if ((error = git_iterator_advance(&wd, workdir)) < 0 &&
|
||||
error = checkout_action_wd_only(data, workdir, wd, pathspec);
|
||||
if (error)
|
||||
goto done;
|
||||
if ((error = git_iterator_advance(wditem, workdir)) < 0 &&
|
||||
error != GIT_ITEROVER)
|
||||
goto fail;
|
||||
|
||||
*wditem_ptr = wd;
|
||||
goto done;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmp == 0) {
|
||||
/* case 4 */
|
||||
act = checkout_action_with_wd(data, delta, wd);
|
||||
*wditem_ptr = git_iterator_advance(&wd, workdir) ? NULL : wd;
|
||||
return act;
|
||||
error = checkout_action_with_wd(action, data, delta, wd);
|
||||
advance = git_iterator_advance;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmp = pfxcomp(wd->path, delta->old_file.path);
|
||||
|
||||
if (cmp == 0) { /* case 5 */
|
||||
if (wd->path[strlen(delta->old_file.path)] != '/')
|
||||
return checkout_action_no_wd(data, delta);
|
||||
return checkout_action_no_wd(action, data, delta);
|
||||
|
||||
if (delta->status == GIT_DELTA_TYPECHANGE) {
|
||||
if (delta->old_file.mode == GIT_FILEMODE_TREE) {
|
||||
act = checkout_action_with_wd(data, delta, wd);
|
||||
if ((error = git_iterator_advance_into(&wd, workdir)) < 0 &&
|
||||
error != GIT_ENOTFOUND)
|
||||
goto fail;
|
||||
*wditem_ptr = wd;
|
||||
return act;
|
||||
error = checkout_action_with_wd(action, data, delta, wd);
|
||||
advance = git_iterator_advance_into;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (delta->new_file.mode == GIT_FILEMODE_TREE ||
|
||||
delta->new_file.mode == GIT_FILEMODE_COMMIT ||
|
||||
delta->old_file.mode == GIT_FILEMODE_COMMIT)
|
||||
{
|
||||
act = checkout_action_with_wd(data, delta, wd);
|
||||
if ((error = git_iterator_advance(&wd, workdir)) < 0 &&
|
||||
error != GIT_ITEROVER)
|
||||
goto fail;
|
||||
*wditem_ptr = wd;
|
||||
return act;
|
||||
error = checkout_action_with_wd(action, data, delta, wd);
|
||||
advance = git_iterator_advance;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
return checkout_action_with_wd_dir(data, delta, wd);
|
||||
return checkout_action_with_wd_dir(action, data, delta, wd);
|
||||
}
|
||||
|
||||
/* case 6 - wd is after delta */
|
||||
return checkout_action_no_wd(data, delta);
|
||||
return checkout_action_no_wd(action, data, delta);
|
||||
}
|
||||
|
||||
fail:
|
||||
*wditem_ptr = NULL;
|
||||
return -1;
|
||||
done:
|
||||
if (!error && advance != NULL &&
|
||||
(error = advance(wditem, workdir)) < 0) {
|
||||
*wditem = NULL;
|
||||
if (error == GIT_ITEROVER)
|
||||
error = 0;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int checkout_remaining_wd_items(
|
||||
@ -846,7 +846,7 @@ static int checkout_conflicts_coalesce_renames(
|
||||
|
||||
/* Juggle entries based on renames */
|
||||
names = git_index_name_entrycount(data->index);
|
||||
|
||||
|
||||
for (i = 0; i < names; i++) {
|
||||
name_entry = git_index_name_get_byindex(data->index, i);
|
||||
|
||||
@ -965,7 +965,7 @@ static int checkout_get_actions(
|
||||
checkout_data *data,
|
||||
git_iterator *workdir)
|
||||
{
|
||||
int error = 0;
|
||||
int error = 0, act;
|
||||
const git_index_entry *wditem;
|
||||
git_vector pathspec = GIT_VECTOR_INIT, *deltas;
|
||||
git_pool pathpool = GIT_POOL_INIT_STRINGPOOL;
|
||||
@ -992,12 +992,9 @@ static int checkout_get_actions(
|
||||
}
|
||||
|
||||
git_vector_foreach(deltas, i, delta) {
|
||||
int act = checkout_action(data, delta, workdir, &wditem, &pathspec);
|
||||
|
||||
if (act < 0) {
|
||||
error = act;
|
||||
error = checkout_action(&act, data, delta, workdir, &wditem, &pathspec);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
actions[i] = act;
|
||||
|
||||
@ -1012,7 +1009,7 @@ static int checkout_get_actions(
|
||||
}
|
||||
|
||||
error = checkout_remaining_wd_items(data, workdir, wditem, &pathspec);
|
||||
if (error < 0)
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
counts[CHECKOUT_ACTION__REMOVE] += data->removes.length;
|
||||
@ -1760,9 +1757,6 @@ static int checkout_create_conflicts(checkout_data *data)
|
||||
|
||||
static void checkout_data_clear(checkout_data *data)
|
||||
{
|
||||
checkout_conflictdata *conflict;
|
||||
size_t i;
|
||||
|
||||
if (data->opts_free_baseline) {
|
||||
git_tree_free(data->opts.baseline);
|
||||
data->opts.baseline = NULL;
|
||||
@ -1771,10 +1765,7 @@ static void checkout_data_clear(checkout_data *data)
|
||||
git_vector_free(&data->removes);
|
||||
git_pool_clear(&data->pool);
|
||||
|
||||
git_vector_foreach(&data->conflicts, i, conflict)
|
||||
git__free(conflict);
|
||||
|
||||
git_vector_free(&data->conflicts);
|
||||
git_vector_free_deep(&data->conflicts);
|
||||
|
||||
git__free(data->pfx);
|
||||
data->pfx = NULL;
|
||||
@ -1966,7 +1957,7 @@ int git_checkout_iterator(
|
||||
* actions to be taken, plus look for conflicts and send notifications,
|
||||
* then loop through conflicts.
|
||||
*/
|
||||
if ((error = checkout_get_actions(&actions, &counts, &data, workdir)) < 0)
|
||||
if ((error = checkout_get_actions(&actions, &counts, &data, workdir)) != 0)
|
||||
goto cleanup;
|
||||
|
||||
data.total_steps = counts[CHECKOUT_ACTION__REMOVE] +
|
||||
@ -1998,9 +1989,6 @@ int git_checkout_iterator(
|
||||
assert(data.completed_steps == data.total_steps);
|
||||
|
||||
cleanup:
|
||||
if (error == GIT_EUSER)
|
||||
giterr_clear();
|
||||
|
||||
if (!error && data.index != NULL &&
|
||||
(data.strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
|
||||
error = git_index_write(data.index);
|
||||
|
||||
121
src/clone.c
121
src/clone.c
@ -115,43 +115,38 @@ static int reference_matches_remote_head(
|
||||
{
|
||||
struct head_info *head_info = (struct head_info *)payload;
|
||||
git_oid oid;
|
||||
int error;
|
||||
|
||||
/* TODO: Should we guard against references
|
||||
* which name doesn't start with refs/heads/ ?
|
||||
*/
|
||||
|
||||
/* Stop looking if we've already found a match */
|
||||
if (head_info->found)
|
||||
error = git_reference_name_to_id(&oid, head_info->repo, reference_name);
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
/* If the reference doesn't exists, it obviously cannot match the
|
||||
* expected oid. */
|
||||
giterr_clear();
|
||||
return 0;
|
||||
|
||||
if (git_reference_name_to_id(
|
||||
&oid,
|
||||
head_info->repo,
|
||||
reference_name) < 0) {
|
||||
/* If the reference doesn't exists, it obviously cannot match the expected oid. */
|
||||
giterr_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (git_oid__cmp(&head_info->remote_head_oid, &oid) == 0) {
|
||||
if (!error && !git_oid__cmp(&head_info->remote_head_oid, &oid)) {
|
||||
/* Determine the local reference name from the remote tracking one */
|
||||
if (git_refspec_transform_l(
|
||||
&head_info->branchname,
|
||||
head_info->refspec,
|
||||
reference_name) < 0)
|
||||
return -1;
|
||||
error = git_refspec_transform_l(
|
||||
&head_info->branchname, head_info->refspec, reference_name);
|
||||
|
||||
if (git_buf_len(&head_info->branchname) > 0) {
|
||||
if (git_buf_sets(
|
||||
if (!error &&
|
||||
git_buf_len(&head_info->branchname) > 0 &&
|
||||
!(error = git_buf_sets(
|
||||
&head_info->branchname,
|
||||
git_buf_cstr(&head_info->branchname) + strlen(GIT_REFS_HEADS_DIR)) < 0)
|
||||
return -1;
|
||||
|
||||
head_info->found = 1;
|
||||
git_buf_cstr(&head_info->branchname) +
|
||||
strlen(GIT_REFS_HEADS_DIR))))
|
||||
{
|
||||
head_info->found = true;
|
||||
error = GIT_ITEROVER;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int update_head_to_new_branch(
|
||||
@ -160,16 +155,11 @@ static int update_head_to_new_branch(
|
||||
const char *name)
|
||||
{
|
||||
git_reference *tracking_branch = NULL;
|
||||
int error;
|
||||
int error = create_tracking_branch(&tracking_branch, repo, target, name);
|
||||
|
||||
if ((error = create_tracking_branch(
|
||||
&tracking_branch,
|
||||
repo,
|
||||
target,
|
||||
name)) < 0)
|
||||
return error;
|
||||
|
||||
error = git_repository_set_head(repo, git_reference_name(tracking_branch));
|
||||
if (!error)
|
||||
error = git_repository_set_head(
|
||||
repo, git_reference_name(tracking_branch));
|
||||
|
||||
git_reference_free(tracking_branch);
|
||||
|
||||
@ -178,34 +168,30 @@ static int update_head_to_new_branch(
|
||||
|
||||
static int update_head_to_remote(git_repository *repo, git_remote *remote)
|
||||
{
|
||||
int retcode = -1;
|
||||
int error = 0;
|
||||
size_t refs_len;
|
||||
git_refspec dummy_spec;
|
||||
const git_remote_head *remote_head, **refs;
|
||||
struct head_info head_info;
|
||||
git_buf remote_master_name = GIT_BUF_INIT;
|
||||
|
||||
if (git_remote_ls(&refs, &refs_len, remote) < 0)
|
||||
return -1;
|
||||
if ((error = git_remote_ls(&refs, &refs_len, remote)) < 0)
|
||||
return error;
|
||||
|
||||
/* Did we just clone an empty repository? */
|
||||
if (refs_len == 0) {
|
||||
if (refs_len == 0)
|
||||
return setup_tracking_config(
|
||||
repo,
|
||||
"master",
|
||||
GIT_REMOTE_ORIGIN,
|
||||
GIT_REFS_HEADS_MASTER_FILE);
|
||||
}
|
||||
repo, "master", GIT_REMOTE_ORIGIN, GIT_REFS_HEADS_MASTER_FILE);
|
||||
|
||||
/* Get the remote's HEAD. This is always the first ref in the list. */
|
||||
remote_head = refs[0];
|
||||
assert(remote_head);
|
||||
|
||||
memset(&head_info, 0, sizeof(head_info));
|
||||
git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid);
|
||||
git_buf_init(&head_info.branchname, 16);
|
||||
head_info.repo = repo;
|
||||
head_info.refspec = git_remote__matching_refspec(remote, GIT_REFS_HEADS_MASTER_FILE);
|
||||
head_info.found = 0;
|
||||
head_info.refspec =
|
||||
git_remote__matching_refspec(remote, GIT_REFS_HEADS_MASTER_FILE);
|
||||
|
||||
if (head_info.refspec == NULL) {
|
||||
memset(&dummy_spec, 0, sizeof(git_refspec));
|
||||
@ -213,50 +199,46 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote)
|
||||
}
|
||||
|
||||
/* Determine the remote tracking reference name from the local master */
|
||||
if (git_refspec_transform_r(
|
||||
if ((error = git_refspec_transform_r(
|
||||
&remote_master_name,
|
||||
head_info.refspec,
|
||||
GIT_REFS_HEADS_MASTER_FILE) < 0)
|
||||
return -1;
|
||||
GIT_REFS_HEADS_MASTER_FILE)) < 0)
|
||||
return error;
|
||||
|
||||
/* Check to see if the remote HEAD points to the remote master */
|
||||
if (reference_matches_remote_head(git_buf_cstr(&remote_master_name), &head_info) < 0)
|
||||
error = reference_matches_remote_head(
|
||||
git_buf_cstr(&remote_master_name), &head_info);
|
||||
if (error < 0 && error != GIT_ITEROVER)
|
||||
goto cleanup;
|
||||
|
||||
if (head_info.found) {
|
||||
retcode = update_head_to_new_branch(
|
||||
error = update_head_to_new_branch(
|
||||
repo,
|
||||
&head_info.remote_head_oid,
|
||||
git_buf_cstr(&head_info.branchname));
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Not master. Check all the other refs. */
|
||||
if (git_reference_foreach_name(
|
||||
repo,
|
||||
reference_matches_remote_head,
|
||||
&head_info) < 0)
|
||||
goto cleanup;
|
||||
error = git_reference_foreach_name(
|
||||
repo, reference_matches_remote_head, &head_info);
|
||||
if (error < 0 && error != GIT_ITEROVER)
|
||||
goto cleanup;
|
||||
|
||||
if (head_info.found) {
|
||||
retcode = update_head_to_new_branch(
|
||||
error = update_head_to_new_branch(
|
||||
repo,
|
||||
&head_info.remote_head_oid,
|
||||
git_buf_cstr(&head_info.branchname));
|
||||
|
||||
goto cleanup;
|
||||
} else {
|
||||
retcode = git_repository_set_head_detached(
|
||||
repo,
|
||||
&head_info.remote_head_oid);
|
||||
goto cleanup;
|
||||
error = git_repository_set_head_detached(
|
||||
repo, &head_info.remote_head_oid);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&remote_master_name);
|
||||
git_buf_free(&head_info.branchname);
|
||||
return retcode;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int update_head_to_branch(
|
||||
@ -359,7 +341,7 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_
|
||||
old_fetchhead = git_remote_update_fetchhead(remote);
|
||||
git_remote_set_update_fetchhead(remote, 0);
|
||||
|
||||
if ((error = git_remote_fetch(remote)) < 0)
|
||||
if ((error = git_remote_fetch(remote)) != 0)
|
||||
goto cleanup;
|
||||
|
||||
if (branch)
|
||||
@ -373,10 +355,12 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_
|
||||
|
||||
cleanup:
|
||||
git_remote_set_update_fetchhead(remote, old_fetchhead);
|
||||
|
||||
/* Go back to the original refspecs */
|
||||
if (git_remote_set_fetch_refspecs(remote, &refspecs) < 0) {
|
||||
git_strarray_free(&refspecs);
|
||||
return -1;
|
||||
{
|
||||
int error_alt = git_remote_set_fetch_refspecs(remote, &refspecs);
|
||||
if (!error)
|
||||
error = error_alt;
|
||||
}
|
||||
|
||||
git_strarray_free(&refspecs);
|
||||
@ -424,9 +408,10 @@ int git_clone(
|
||||
git_remote_free(origin);
|
||||
}
|
||||
|
||||
if (error < 0) {
|
||||
if (error != 0) {
|
||||
git_repository_free(repo);
|
||||
repo = NULL;
|
||||
|
||||
(void)git_futils_rmdir_r(local_path, NULL, rmdir_flags);
|
||||
}
|
||||
|
||||
|
||||
67
src/common.h
67
src/common.h
@ -62,7 +62,7 @@
|
||||
* Check a return value and propogate result if non-zero.
|
||||
*/
|
||||
#define GITERR_CHECK_ERROR(code) \
|
||||
do { int _err = (code); if (_err < 0) return _err; } while (0)
|
||||
do { int _err = (code); if (_err) return _err; } while (0)
|
||||
|
||||
/**
|
||||
* Set the error message for this thread, formatting as needed.
|
||||
@ -75,29 +75,62 @@ void giterr_set(int error_class, const char *string, ...);
|
||||
*/
|
||||
int giterr_set_regex(const regex_t *regex, int error_code);
|
||||
|
||||
/**
|
||||
* Set error message for user callback if needed.
|
||||
*
|
||||
* If the error code in non-zero and no error message is set, this
|
||||
* sets a generic error message.
|
||||
*
|
||||
* @return This always returns the `error_code` parameter.
|
||||
*/
|
||||
GIT_INLINE(int) giterr_set_after_callback_function(
|
||||
int error_code, const char *action)
|
||||
{
|
||||
if (error_code) {
|
||||
const git_error *e = giterr_last();
|
||||
if (!e || !e->message)
|
||||
giterr_set(e ? e->klass : GITERR_CALLBACK,
|
||||
"%s callback returned %d", action, error_code);
|
||||
}
|
||||
return error_code;
|
||||
}
|
||||
|
||||
#ifdef GIT_WIN32
|
||||
#define giterr_set_after_callback(code) \
|
||||
giterr_set_after_callback_function((code), __FUNCTION__)
|
||||
#else
|
||||
#define giterr_set_after_callback(code) \
|
||||
giterr_set_after_callback_function((code), __func__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gets the system error code for this thread.
|
||||
*/
|
||||
GIT_INLINE(int) giterr_system_last(void)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return GetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
int giterr_system_last(void);
|
||||
|
||||
/**
|
||||
* Sets the system error code for this thread.
|
||||
*/
|
||||
GIT_INLINE(void) giterr_system_set(int code)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
SetLastError(code);
|
||||
#else
|
||||
errno = code;
|
||||
#endif
|
||||
}
|
||||
void giterr_system_set(int code);
|
||||
|
||||
/**
|
||||
* Structure to preserve libgit2 error state
|
||||
*/
|
||||
typedef struct {
|
||||
int error_code;
|
||||
git_error error_msg;
|
||||
} git_error_state;
|
||||
|
||||
/**
|
||||
* Capture current error state to restore later, returning error code.
|
||||
* If `error_code` is zero, this does nothing and returns zero.
|
||||
*/
|
||||
int giterr_capture(git_error_state *state, int error_code);
|
||||
|
||||
/**
|
||||
* Restore error state to a previous value, returning saved error code.
|
||||
*/
|
||||
int giterr_restore(git_error_state *state);
|
||||
|
||||
/**
|
||||
* Check a versioned structure for validity
|
||||
|
||||
258
src/config.c
258
src/config.c
@ -480,47 +480,45 @@ int git_config_foreach(
|
||||
int git_config_backend_foreach_match(
|
||||
git_config_backend *backend,
|
||||
const char *regexp,
|
||||
int (*fn)(const git_config_entry *, void *),
|
||||
void *data)
|
||||
git_config_foreach_cb cb,
|
||||
void *payload)
|
||||
{
|
||||
git_config_entry *entry;
|
||||
git_config_iterator* iter;
|
||||
regex_t regex;
|
||||
int result = 0;
|
||||
int error = 0;
|
||||
|
||||
if (regexp != NULL) {
|
||||
if ((result = regcomp(®ex, regexp, REG_EXTENDED)) < 0) {
|
||||
giterr_set_regex(®ex, result);
|
||||
if ((error = regcomp(®ex, regexp, REG_EXTENDED)) < 0) {
|
||||
giterr_set_regex(®ex, error);
|
||||
regfree(®ex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((result = backend->iterator(&iter, backend)) < 0) {
|
||||
if ((error = backend->iterator(&iter, backend)) < 0) {
|
||||
iter = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(!(iter->next(&entry, iter) < 0)) {
|
||||
while (!(iter->next(&entry, iter) < 0)) {
|
||||
/* skip non-matching keys if regexp was provided */
|
||||
if (regexp && regexec(®ex, entry->name, 0, NULL, 0) != 0)
|
||||
continue;
|
||||
|
||||
/* abort iterator on non-zero return value */
|
||||
if (fn(entry, data)) {
|
||||
giterr_clear();
|
||||
result = GIT_EUSER;
|
||||
goto cleanup;
|
||||
if ((error = cb(entry, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (regexp != NULL)
|
||||
regfree(®ex);
|
||||
|
||||
iter->free(iter);
|
||||
|
||||
return result;
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_config_foreach_match(
|
||||
@ -536,10 +534,9 @@ int git_config_foreach_match(
|
||||
if ((error = git_config_iterator_glob_new(&iter, cfg, regexp)) < 0)
|
||||
return error;
|
||||
|
||||
while ((error = git_config_next(&entry, iter)) == 0) {
|
||||
if(cb(entry, payload)) {
|
||||
giterr_clear();
|
||||
error = GIT_EUSER;
|
||||
while (!(error = git_config_next(&entry, iter))) {
|
||||
if ((error = cb(entry, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -620,55 +617,6 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
|
||||
/***********
|
||||
* Getters
|
||||
***********/
|
||||
int git_config_get_mapped(
|
||||
int *out,
|
||||
const git_config *cfg,
|
||||
const char *name,
|
||||
const git_cvar_map *maps,
|
||||
size_t map_n)
|
||||
{
|
||||
const char *value;
|
||||
int ret;
|
||||
|
||||
if ((ret = git_config_get_string(&value, cfg, name)) < 0)
|
||||
return ret;
|
||||
|
||||
return git_config_lookup_map_value(out, maps, map_n, value);
|
||||
}
|
||||
|
||||
int git_config_get_int64(int64_t *out, const git_config *cfg, const char *name)
|
||||
{
|
||||
const char *value;
|
||||
int ret;
|
||||
|
||||
if ((ret = git_config_get_string(&value, cfg, name)) < 0)
|
||||
return ret;
|
||||
|
||||
return git_config_parse_int64(out, value);
|
||||
}
|
||||
|
||||
int git_config_get_int32(int32_t *out, const git_config *cfg, const char *name)
|
||||
{
|
||||
const char *value;
|
||||
int ret;
|
||||
|
||||
if ((ret = git_config_get_string(&value, cfg, name)) < 0)
|
||||
return ret;
|
||||
|
||||
return git_config_parse_int32(out, value);
|
||||
}
|
||||
|
||||
static int get_string_at_file(const char **out, const git_config_backend *file, const char *name)
|
||||
{
|
||||
const git_config_entry *entry;
|
||||
int res;
|
||||
|
||||
res = file->get(file, name, &entry);
|
||||
if (!res)
|
||||
*out = entry->value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int config_error_notfound(const char *name)
|
||||
{
|
||||
@ -676,67 +624,163 @@ static int config_error_notfound(const char *name)
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
static int get_string(const char **out, const git_config *cfg, const char *name)
|
||||
enum {
|
||||
GET_ALL_ERRORS = 0,
|
||||
GET_NO_MISSING = 1,
|
||||
GET_NO_ERRORS = 2
|
||||
};
|
||||
|
||||
static int get_entry(
|
||||
const git_config_entry **out,
|
||||
const git_config *cfg,
|
||||
const char *name,
|
||||
bool normalize_name,
|
||||
int want_errors)
|
||||
{
|
||||
int res = GIT_ENOTFOUND;
|
||||
const char *key = name;
|
||||
char *normalized = NULL;
|
||||
size_t i;
|
||||
file_internal *internal;
|
||||
unsigned int i;
|
||||
int res;
|
||||
|
||||
*out = NULL;
|
||||
|
||||
if (normalize_name) {
|
||||
if ((res = git_config__normalize_name(name, &normalized)) < 0)
|
||||
goto cleanup;
|
||||
key = normalized;
|
||||
}
|
||||
|
||||
git_vector_foreach(&cfg->files, i, internal) {
|
||||
if (!internal || !internal->file)
|
||||
continue;
|
||||
|
||||
res = get_string_at_file(out, internal->file, name);
|
||||
res = internal->file->get(internal->file, key, out);
|
||||
if (res != GIT_ENOTFOUND)
|
||||
return res;
|
||||
break;
|
||||
}
|
||||
|
||||
return config_error_notfound(name);
|
||||
git__free(normalized);
|
||||
|
||||
cleanup:
|
||||
if (res == GIT_ENOTFOUND)
|
||||
res = (want_errors > GET_ALL_ERRORS) ? 0 : config_error_notfound(name);
|
||||
else if (res && (want_errors == GET_NO_ERRORS)) {
|
||||
giterr_clear();
|
||||
res = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int git_config_get_entry(
|
||||
const git_config_entry **out, const git_config *cfg, const char *name)
|
||||
{
|
||||
return get_entry(out, cfg, name, true, GET_ALL_ERRORS);
|
||||
}
|
||||
|
||||
int git_config__lookup_entry(
|
||||
const git_config_entry **out,
|
||||
const git_config *cfg,
|
||||
const char *key,
|
||||
bool no_errors)
|
||||
{
|
||||
return get_entry(
|
||||
out, cfg, key, false, no_errors ? GET_NO_ERRORS : GET_NO_MISSING);
|
||||
}
|
||||
|
||||
int git_config_get_mapped(
|
||||
int *out,
|
||||
const git_config *cfg,
|
||||
const char *name,
|
||||
const git_cvar_map *maps,
|
||||
size_t map_n)
|
||||
{
|
||||
const git_config_entry *entry;
|
||||
int ret;
|
||||
|
||||
if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
||||
return ret;
|
||||
|
||||
return git_config_lookup_map_value(out, maps, map_n, entry->value);
|
||||
}
|
||||
|
||||
int git_config_get_int64(int64_t *out, const git_config *cfg, const char *name)
|
||||
{
|
||||
const git_config_entry *entry;
|
||||
int ret;
|
||||
|
||||
if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
||||
return ret;
|
||||
|
||||
return git_config_parse_int64(out, entry->value);
|
||||
}
|
||||
|
||||
int git_config_get_int32(int32_t *out, const git_config *cfg, const char *name)
|
||||
{
|
||||
const git_config_entry *entry;
|
||||
int ret;
|
||||
|
||||
if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
||||
return ret;
|
||||
|
||||
return git_config_parse_int32(out, entry->value);
|
||||
}
|
||||
|
||||
int git_config_get_bool(int *out, const git_config *cfg, const char *name)
|
||||
{
|
||||
const char *value = NULL;
|
||||
const git_config_entry *entry;
|
||||
int ret;
|
||||
|
||||
if ((ret = get_string(&value, cfg, name)) < 0)
|
||||
if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
|
||||
return ret;
|
||||
|
||||
return git_config_parse_bool(out, value);
|
||||
return git_config_parse_bool(out, entry->value);
|
||||
}
|
||||
|
||||
int git_config_get_string(const char **out, const git_config *cfg, const char *name)
|
||||
int git_config_get_string(
|
||||
const char **out, const git_config *cfg, const char *name)
|
||||
{
|
||||
int ret;
|
||||
const char *str = NULL;
|
||||
|
||||
if ((ret = get_string(&str, cfg, name)) < 0)
|
||||
return ret;
|
||||
|
||||
*out = str == NULL ? "" : str;
|
||||
return 0;
|
||||
const git_config_entry *entry;
|
||||
int ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
|
||||
*out = !ret ? (entry->value ? entry->value : "") : NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int git_config_get_entry(const git_config_entry **out, const git_config *cfg, const char *name)
|
||||
const char *git_config__get_string_force(
|
||||
const git_config *cfg, const char *key, const char *fallback_value)
|
||||
{
|
||||
file_internal *internal;
|
||||
unsigned int i;
|
||||
git_config_backend *file;
|
||||
int ret;
|
||||
const git_config_entry *entry;
|
||||
get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
|
||||
return (entry && entry->value) ? entry->value : fallback_value;
|
||||
}
|
||||
|
||||
*out = NULL;
|
||||
int git_config__get_bool_force(
|
||||
const git_config *cfg, const char *key, int fallback_value)
|
||||
{
|
||||
int val = fallback_value;
|
||||
const git_config_entry *entry;
|
||||
|
||||
git_vector_foreach(&cfg->files, i, internal) {
|
||||
if (!internal || !internal->file)
|
||||
continue;
|
||||
file = internal->file;
|
||||
get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
|
||||
|
||||
ret = file->get(file, name, out);
|
||||
if (ret != GIT_ENOTFOUND)
|
||||
return ret;
|
||||
}
|
||||
if (entry && git_config_parse_bool(&val, entry->value) < 0)
|
||||
giterr_clear();
|
||||
|
||||
return config_error_notfound(name);
|
||||
return val;
|
||||
}
|
||||
|
||||
int git_config__get_int_force(
|
||||
const git_config *cfg, const char *key, int fallback_value)
|
||||
{
|
||||
int32_t val = (int32_t)fallback_value;
|
||||
const git_config_entry *entry;
|
||||
|
||||
get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
|
||||
|
||||
if (entry && git_config_parse_int32(&val, entry->value) < 0)
|
||||
giterr_clear();
|
||||
|
||||
return (int)val;
|
||||
}
|
||||
|
||||
int git_config_get_multivar_foreach(
|
||||
@ -753,9 +797,10 @@ int git_config_get_multivar_foreach(
|
||||
found = 0;
|
||||
while ((err = iter->next(&entry, iter)) == 0) {
|
||||
found = 1;
|
||||
if(cb(entry, payload)) {
|
||||
iter->free(iter);
|
||||
return GIT_EUSER;
|
||||
|
||||
if ((err = cb(entry, payload)) != 0) {
|
||||
giterr_set_after_callback(err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1070,7 +1115,7 @@ int git_config_parse_int64(int64_t *out, const char *value)
|
||||
const char *num_end;
|
||||
int64_t num;
|
||||
|
||||
if (git__strtol64(&num, value, &num_end, 0) < 0)
|
||||
if (!value || git__strtol64(&num, value, &num_end, 0) < 0)
|
||||
goto fail_parse;
|
||||
|
||||
switch (*num_end) {
|
||||
@ -1167,7 +1212,6 @@ struct rename_data {
|
||||
git_config *config;
|
||||
git_buf *name;
|
||||
size_t old_len;
|
||||
int actual_error;
|
||||
};
|
||||
|
||||
static int rename_config_entries_cb(
|
||||
@ -1190,8 +1234,6 @@ static int rename_config_entries_cb(
|
||||
if (!error)
|
||||
error = git_config_delete_entry(data->config, entry->name);
|
||||
|
||||
data->actual_error = error; /* preserve actual error code */
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1216,7 +1258,6 @@ int git_config_rename_section(
|
||||
data.config = config;
|
||||
data.name = &replace;
|
||||
data.old_len = strlen(old_section_name) + 1;
|
||||
data.actual_error = 0;
|
||||
|
||||
if ((error = git_buf_join(&replace, '.', new_section_name, "")) < 0)
|
||||
goto cleanup;
|
||||
@ -1233,9 +1274,6 @@ int git_config_rename_section(
|
||||
error = git_config_foreach_match(
|
||||
config, git_buf_cstr(&pattern), rename_config_entries_cb, &data);
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
error = data.actual_error;
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&pattern);
|
||||
git_buf_free(&replace);
|
||||
|
||||
21
src/config.h
21
src/config.h
@ -51,5 +51,26 @@ extern int git_config_file__ondisk(git_config_backend **out, const char *path);
|
||||
|
||||
extern int git_config__normalize_name(const char *in, char **out);
|
||||
|
||||
/* internal only: does not normalize key and sets out to NULL if not found */
|
||||
extern int git_config__lookup_entry(
|
||||
const git_config_entry **out,
|
||||
const git_config *cfg,
|
||||
const char *key,
|
||||
bool no_errors);
|
||||
|
||||
/*
|
||||
* Lookup functions that cannot fail. These functions look up a config
|
||||
* value and return a fallback value if the value is missing or if any
|
||||
* failures occur while trying to access the value.
|
||||
*/
|
||||
|
||||
extern const char *git_config__get_string_force(
|
||||
const git_config *cfg, const char *key, const char *fallback_value);
|
||||
|
||||
extern int git_config__get_bool_force(
|
||||
const git_config *cfg, const char *key, int fallback_value);
|
||||
|
||||
extern int git_config__get_int_force(
|
||||
const git_config *cfg, const char *key, int fallback_value);
|
||||
|
||||
#endif
|
||||
|
||||
@ -78,22 +78,22 @@ int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar)
|
||||
struct map_data *data = &_cvar_maps[(int)cvar];
|
||||
git_config *config;
|
||||
int error;
|
||||
const git_config_entry *entry;
|
||||
|
||||
error = git_repository_config__weakptr(&config, repo);
|
||||
if (error < 0)
|
||||
if ((error = git_repository_config__weakptr(&config, repo)) < 0)
|
||||
return error;
|
||||
|
||||
if (data->maps)
|
||||
error = git_config_get_mapped(
|
||||
out, config, data->cvar_name, data->maps, data->map_count);
|
||||
else
|
||||
error = git_config_get_bool(out, config, data->cvar_name);
|
||||
git_config__lookup_entry(&entry, config, data->cvar_name, false);
|
||||
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
if (!entry)
|
||||
*out = data->default_value;
|
||||
}
|
||||
else if (error < 0)
|
||||
else if (data->maps)
|
||||
error = git_config_lookup_map_value(
|
||||
out, data->maps, data->map_count, entry->value);
|
||||
else
|
||||
error = git_config_parse_bool(out, entry->value);
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
repo->cvar_cache[(int)cvar] = *out;
|
||||
|
||||
@ -404,20 +404,12 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
|
||||
/*
|
||||
* Internal function that actually gets the value in string form
|
||||
*/
|
||||
static int config_get(const git_config_backend *cfg, const char *name, const git_config_entry **out)
|
||||
static int config_get(const git_config_backend *cfg, const char *key, const git_config_entry **out)
|
||||
{
|
||||
diskfile_backend *b = (diskfile_backend *)cfg;
|
||||
char *key;
|
||||
khiter_t pos;
|
||||
int error;
|
||||
khiter_t pos = git_strmap_lookup_index(b->values, key);
|
||||
cvar_t *var;
|
||||
|
||||
if ((error = git_config__normalize_name(name, &key)) < 0)
|
||||
return error;
|
||||
|
||||
pos = git_strmap_lookup_index(b->values, key);
|
||||
git__free(key);
|
||||
|
||||
/* no error message; the config system will write one */
|
||||
if (!git_strmap_valid_index(b->values, pos))
|
||||
return GIT_ENOTFOUND;
|
||||
@ -427,7 +419,6 @@ static int config_get(const git_config_backend *cfg, const char *name, const git
|
||||
var = var->next;
|
||||
|
||||
*out = var->entry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
146
src/diff.c
146
src/diff.c
@ -49,16 +49,29 @@ static git_diff_delta *diff_delta__alloc(
|
||||
return delta;
|
||||
}
|
||||
|
||||
static int diff_notify(
|
||||
const git_diff *diff,
|
||||
const git_diff_delta *delta,
|
||||
const char *matched_pathspec)
|
||||
static int diff_insert_delta(
|
||||
git_diff *diff, git_diff_delta *delta, const char *matched_pathspec)
|
||||
{
|
||||
if (!diff->opts.notify_cb)
|
||||
return 0;
|
||||
int error = 0;
|
||||
|
||||
return diff->opts.notify_cb(
|
||||
diff, delta, matched_pathspec, diff->opts.notify_payload);
|
||||
if (diff->opts.notify_cb) {
|
||||
error = diff->opts.notify_cb(
|
||||
diff, delta, matched_pathspec, diff->opts.notify_payload);
|
||||
|
||||
if (error) {
|
||||
git__free(delta);
|
||||
|
||||
if (error > 0) /* positive value means to skip this delta */
|
||||
return 0;
|
||||
else /* negative value means to cancel diff */
|
||||
return giterr_set_after_callback_function(error, "git_diff");
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = git_vector_insert(&diff->deltas, delta)) < 0)
|
||||
git__free(delta);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int diff_delta__from_one(
|
||||
@ -68,7 +81,6 @@ static int diff_delta__from_one(
|
||||
{
|
||||
git_diff_delta *delta;
|
||||
const char *matched_pathspec;
|
||||
int notify_res;
|
||||
|
||||
if ((entry->flags & GIT_IDXENTRY_VALID) != 0)
|
||||
return 0;
|
||||
@ -111,21 +123,12 @@ static int diff_delta__from_one(
|
||||
!git_oid_iszero(&delta->new_file.oid))
|
||||
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
|
||||
|
||||
notify_res = diff_notify(diff, delta, matched_pathspec);
|
||||
|
||||
if (notify_res)
|
||||
git__free(delta);
|
||||
else if (git_vector_insert(&diff->deltas, delta) < 0) {
|
||||
git__free(delta);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return notify_res < 0 ? GIT_EUSER : 0;
|
||||
return diff_insert_delta(diff, delta, matched_pathspec);
|
||||
}
|
||||
|
||||
static int diff_delta__from_two(
|
||||
git_diff *diff,
|
||||
git_delta_t status,
|
||||
git_delta_t status,
|
||||
const git_index_entry *old_entry,
|
||||
uint32_t old_mode,
|
||||
const git_index_entry *new_entry,
|
||||
@ -134,7 +137,6 @@ static int diff_delta__from_two(
|
||||
const char *matched_pathspec)
|
||||
{
|
||||
git_diff_delta *delta;
|
||||
int notify_res;
|
||||
const char *canonical_path = old_entry->path;
|
||||
|
||||
if (status == GIT_DELTA_UNMODIFIED &&
|
||||
@ -173,16 +175,7 @@ static int diff_delta__from_two(
|
||||
if (new_oid || !git_oid_iszero(&new_entry->oid))
|
||||
delta->new_file.flags |= GIT_DIFF_FLAG_VALID_OID;
|
||||
|
||||
notify_res = diff_notify(diff, delta, matched_pathspec);
|
||||
|
||||
if (notify_res)
|
||||
git__free(delta);
|
||||
else if (git_vector_insert(&diff->deltas, delta) < 0) {
|
||||
git__free(delta);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return notify_res < 0 ? GIT_EUSER : 0;
|
||||
return diff_insert_delta(diff, delta, matched_pathspec);
|
||||
}
|
||||
|
||||
static git_diff_delta *diff_delta__last_for_item(
|
||||
@ -304,26 +297,6 @@ bool git_diff_delta__should_skip(
|
||||
}
|
||||
|
||||
|
||||
static int config_bool(git_config *cfg, const char *name, int defvalue)
|
||||
{
|
||||
int val = defvalue;
|
||||
|
||||
if (git_config_get_bool(&val, cfg, name) < 0)
|
||||
giterr_clear();
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int config_int(git_config *cfg, const char *name, int defvalue)
|
||||
{
|
||||
int val = defvalue;
|
||||
|
||||
if (git_config_get_int32(&val, cfg, name) < 0)
|
||||
giterr_clear();
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static const char *diff_mnemonic_prefix(
|
||||
git_iterator_type_t type, bool left_side)
|
||||
{
|
||||
@ -422,8 +395,8 @@ static int diff_list_apply_options(
|
||||
diff->opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
|
||||
|
||||
/* load config values that affect diff behavior */
|
||||
if (git_repository_config__weakptr(&cfg, repo) < 0)
|
||||
return -1;
|
||||
if ((val = git_repository_config__weakptr(&cfg, repo)) < 0)
|
||||
return val;
|
||||
|
||||
if (!git_repository__cvar(&val, repo, GIT_CVAR_SYMLINKS) && val)
|
||||
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_HAS_SYMLINKS;
|
||||
@ -445,7 +418,7 @@ static int diff_list_apply_options(
|
||||
|
||||
/* If not given explicit `opts`, check `diff.xyz` configs */
|
||||
if (!opts) {
|
||||
int context = config_int(cfg, "diff.context", 3);
|
||||
int context = git_config__get_int_force(cfg, "diff.context", 3);
|
||||
diff->opts.context_lines = context >= 0 ? (uint16_t)context : 3;
|
||||
|
||||
/* add other defaults here */
|
||||
@ -460,12 +433,11 @@ static int diff_list_apply_options(
|
||||
|
||||
/* if ignore_submodules not explicitly set, check diff config */
|
||||
if (diff->opts.ignore_submodules <= 0) {
|
||||
const char *str;
|
||||
const git_config_entry *entry;
|
||||
git_config__lookup_entry(&entry, cfg, "diff.ignoresubmodules", true);
|
||||
|
||||
if (git_config_get_string(&str , cfg, "diff.ignoreSubmodules") < 0)
|
||||
giterr_clear();
|
||||
else if (str != NULL &&
|
||||
git_submodule_parse_ignore(&diff->opts.ignore_submodules, str) < 0)
|
||||
if (entry && git_submodule_parse_ignore(
|
||||
&diff->opts.ignore_submodules, entry->value) < 0)
|
||||
giterr_clear();
|
||||
}
|
||||
|
||||
@ -474,9 +446,9 @@ static int diff_list_apply_options(
|
||||
const char *use_old = DIFF_OLD_PREFIX_DEFAULT;
|
||||
const char *use_new = DIFF_NEW_PREFIX_DEFAULT;
|
||||
|
||||
if (config_bool(cfg, "diff.noprefix", 0)) {
|
||||
if (git_config__get_bool_force(cfg, "diff.noprefix", 0))
|
||||
use_old = use_new = "";
|
||||
} else if (config_bool(cfg, "diff.mnemonicprefix", 0)) {
|
||||
else if (git_config__get_bool_force(cfg, "diff.mnemonicprefix", 0)) {
|
||||
use_old = diff_mnemonic_prefix(diff->old_src, true);
|
||||
use_new = diff_mnemonic_prefix(diff->new_src, false);
|
||||
}
|
||||
@ -504,14 +476,7 @@ static int diff_list_apply_options(
|
||||
|
||||
static void diff_list_free(git_diff *diff)
|
||||
{
|
||||
git_diff_delta *delta;
|
||||
unsigned int i;
|
||||
|
||||
git_vector_foreach(&diff->deltas, i, delta) {
|
||||
git__free(delta);
|
||||
diff->deltas.contents[i] = NULL;
|
||||
}
|
||||
git_vector_free(&diff->deltas);
|
||||
git_vector_free_deep(&diff->deltas);
|
||||
|
||||
git_pathspec__vfree(&diff->pathspec);
|
||||
git_pool_clear(&diff->pool);
|
||||
@ -682,6 +647,7 @@ static int maybe_modified(
|
||||
unsigned int nmode = nitem->mode;
|
||||
bool new_is_workdir = (info->new_iter->type == GIT_ITERATOR_TYPE_WORKDIR);
|
||||
const char *matched_pathspec;
|
||||
int error = 0;
|
||||
|
||||
if (!git_pathspec__match(
|
||||
&diff->pathspec, oitem->path,
|
||||
@ -716,10 +682,9 @@ static int maybe_modified(
|
||||
if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE))
|
||||
status = GIT_DELTA_TYPECHANGE;
|
||||
else {
|
||||
if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 ||
|
||||
diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
if (!(error = diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem)))
|
||||
error = diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -741,8 +706,8 @@ static int maybe_modified(
|
||||
/* TODO: add check against index file st_mtime to avoid racy-git */
|
||||
|
||||
if (S_ISGITLINK(nmode)) {
|
||||
if (maybe_modified_submodule(&status, &noid, diff, info) < 0)
|
||||
return -1;
|
||||
if ((error = maybe_modified_submodule(&status, &noid, diff, info)) < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* if the stat data looks different, then mark modified - this just
|
||||
@ -769,9 +734,9 @@ static int maybe_modified(
|
||||
*/
|
||||
if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->oid)) {
|
||||
if (git_oid_iszero(&noid)) {
|
||||
if (git_diff__oid_for_file(diff->repo,
|
||||
nitem->path, nitem->mode, nitem->file_size, &noid) < 0)
|
||||
return -1;
|
||||
if ((error = git_diff__oid_for_file(diff->repo,
|
||||
nitem->path, nitem->mode, nitem->file_size, &noid)) < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* if oid matches, then mark unmodified (except submodules, where
|
||||
@ -926,7 +891,7 @@ static int handle_unmatched_new_item(
|
||||
git_diff_delta *last;
|
||||
|
||||
/* attempt to insert record for this directory */
|
||||
if ((error = diff_delta__from_one(diff, delta_type, nitem)) < 0)
|
||||
if ((error = diff_delta__from_one(diff, delta_type, nitem)) != 0)
|
||||
return error;
|
||||
|
||||
/* if delta wasn't created (because of rules), just skip ahead */
|
||||
@ -1005,7 +970,7 @@ static int handle_unmatched_new_item(
|
||||
}
|
||||
|
||||
/* Actually create the record for this item if necessary */
|
||||
if ((error = diff_delta__from_one(diff, delta_type, nitem)) < 0)
|
||||
if ((error = diff_delta__from_one(diff, delta_type, nitem)) != 0)
|
||||
return error;
|
||||
|
||||
/* If user requested TYPECHANGE records, then check for that instead of
|
||||
@ -1030,7 +995,7 @@ static int handle_unmatched_old_item(
|
||||
git_diff *diff, diff_in_progress *info)
|
||||
{
|
||||
int error = diff_delta__from_one(diff, GIT_DELTA_DELETED, info->oitem);
|
||||
if (error < 0)
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
/* if we are generating TYPECHANGE records then check for that
|
||||
@ -1364,7 +1329,7 @@ int git_diff__paired_foreach(
|
||||
int (*cb)(git_diff_delta *h2i, git_diff_delta *i2w, void *payload),
|
||||
void *payload)
|
||||
{
|
||||
int cmp;
|
||||
int cmp, error = 0;
|
||||
git_diff_delta *h2i, *i2w;
|
||||
size_t i, j, i_max, j_max;
|
||||
int (*strcomp)(const char *, const char *) = git__strcmp;
|
||||
@ -1420,18 +1385,17 @@ int git_diff__paired_foreach(
|
||||
strcomp(h2i->new_file.path, i2w->old_file.path);
|
||||
|
||||
if (cmp < 0) {
|
||||
if (cb(h2i, NULL, payload))
|
||||
return GIT_EUSER;
|
||||
i++;
|
||||
i++; i2w = NULL;
|
||||
} else if (cmp > 0) {
|
||||
if (cb(NULL, i2w, payload))
|
||||
return GIT_EUSER;
|
||||
j++;
|
||||
j++; h2i = NULL;
|
||||
} else {
|
||||
if (cb(h2i, i2w, payload))
|
||||
return GIT_EUSER;
|
||||
i++; j++;
|
||||
}
|
||||
|
||||
if ((error = cb(h2i, i2w, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* restore case-insensitive delta sort */
|
||||
@ -1447,5 +1411,5 @@ int git_diff__paired_foreach(
|
||||
git_vector_sort(&idx2wd->deltas);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "strmap.h"
|
||||
#include "map.h"
|
||||
#include "buf_text.h"
|
||||
#include "config.h"
|
||||
#include "repository.h"
|
||||
|
||||
GIT__USE_STRMAP;
|
||||
@ -130,14 +131,14 @@ static git_diff_driver_registry *git_repository_driver_registry(
|
||||
static int git_diff_driver_load(
|
||||
git_diff_driver **out, git_repository *repo, const char *driver_name)
|
||||
{
|
||||
int error = 0, bval;
|
||||
int error = 0;
|
||||
git_diff_driver_registry *reg;
|
||||
git_diff_driver *drv;
|
||||
size_t namelen = strlen(driver_name);
|
||||
khiter_t pos;
|
||||
git_config *cfg;
|
||||
git_buf name = GIT_BUF_INIT;
|
||||
const char *val;
|
||||
const git_config_entry *ce;
|
||||
bool found_driver = false;
|
||||
|
||||
reg = git_repository_driver_registry(repo);
|
||||
@ -164,23 +165,21 @@ static int git_diff_driver_load(
|
||||
|
||||
if ((error = git_buf_printf(&name, "diff.%s.binary", driver_name)) < 0)
|
||||
goto done;
|
||||
if ((error = git_config_get_string(&val, cfg, name.ptr)) < 0) {
|
||||
if (error != GIT_ENOTFOUND)
|
||||
goto done;
|
||||
/* diff.<driver>.binary unspecified, so just continue */
|
||||
giterr_clear();
|
||||
} else if (git_config_parse_bool(&bval, val) < 0) {
|
||||
/* TODO: warn that diff.<driver>.binary has invalid value */
|
||||
giterr_clear();
|
||||
} else if (bval) {
|
||||
|
||||
switch (git_config__get_bool_force(cfg, name.ptr, -1)) {
|
||||
case true:
|
||||
/* if diff.<driver>.binary is true, just return the binary driver */
|
||||
*out = &global_drivers[DIFF_DRIVER_BINARY];
|
||||
goto done;
|
||||
} else {
|
||||
case false:
|
||||
/* if diff.<driver>.binary is false, force binary checks off */
|
||||
/* but still may have custom function context patterns, etc. */
|
||||
drv->binary_flags = GIT_DIFF_FORCE_TEXT;
|
||||
found_driver = true;
|
||||
break;
|
||||
default:
|
||||
/* diff.<driver>.binary unspecified, so just continue */
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: warn if diff.<name>.command or diff.<name>.textconv are set */
|
||||
@ -211,16 +210,16 @@ static int git_diff_driver_load(
|
||||
|
||||
git_buf_truncate(&name, namelen + strlen("diff.."));
|
||||
git_buf_put(&name, "wordregex", strlen("wordregex"));
|
||||
if ((error = git_config_get_string(&val, cfg, name.ptr)) < 0) {
|
||||
if (error != GIT_ENOTFOUND)
|
||||
goto done;
|
||||
giterr_clear(); /* no diff.<driver>.wordregex, so just continue */
|
||||
} else if ((error = regcomp(&drv->word_pattern, val, REG_EXTENDED)) != 0) {
|
||||
/* TODO: warning about bad regex instead of failure */
|
||||
if ((error = git_config__lookup_entry(&ce, cfg, name.ptr, false)) < 0)
|
||||
goto done;
|
||||
if (!ce || !ce->value)
|
||||
/* no diff.<driver>.wordregex, so just continue */;
|
||||
else if (!(error = regcomp(&drv->word_pattern, ce->value, REG_EXTENDED)))
|
||||
found_driver = true;
|
||||
else {
|
||||
/* TODO: warn about bad regex instead of failure */
|
||||
error = giterr_set_regex(&drv->word_pattern, error);
|
||||
goto done;
|
||||
} else {
|
||||
found_driver = true;
|
||||
}
|
||||
|
||||
/* TODO: look up diff.<driver>.algorithm to turn on minimal / patience
|
||||
|
||||
@ -193,21 +193,18 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int diff_patch_file_callback(
|
||||
static int diff_patch_invoke_file_callback(
|
||||
git_patch *patch, git_diff_output *output)
|
||||
{
|
||||
float progress;
|
||||
float progress = patch->diff ?
|
||||
((float)patch->delta_index / patch->diff->deltas.length) : 1.0f;
|
||||
|
||||
if (!output->file_cb)
|
||||
return 0;
|
||||
|
||||
progress = patch->diff ?
|
||||
((float)patch->delta_index / patch->diff->deltas.length) : 1.0f;
|
||||
|
||||
if (output->file_cb(patch->delta, progress, output->payload) != 0)
|
||||
output->error = GIT_EUSER;
|
||||
|
||||
return output->error;
|
||||
return giterr_set_after_callback_function(
|
||||
output->file_cb(patch->delta, progress, output->payload),
|
||||
"git_patch");
|
||||
}
|
||||
|
||||
static int diff_patch_generate(git_patch *patch, git_diff_output *output)
|
||||
@ -229,7 +226,7 @@ static int diff_patch_generate(git_patch *patch, git_diff_output *output)
|
||||
return 0;
|
||||
|
||||
if (output->diff_cb != NULL &&
|
||||
!(error = output->diff_cb(output, patch)))
|
||||
(error = output->diff_cb(output, patch)) < 0)
|
||||
patch->flags |= GIT_DIFF_PATCH_DIFFED;
|
||||
|
||||
return error;
|
||||
@ -272,9 +269,10 @@ int git_diff_foreach(
|
||||
size_t idx;
|
||||
git_patch patch;
|
||||
|
||||
if (diff_required(diff, "git_diff_foreach") < 0)
|
||||
return -1;
|
||||
if ((error = diff_required(diff, "git_diff_foreach")) < 0)
|
||||
return error;
|
||||
|
||||
memset(&xo, 0, sizeof(xo));
|
||||
diff_output_init(
|
||||
&xo.output, &diff->opts, file_cb, hunk_cb, data_cb, payload);
|
||||
git_xdiff_init(&xo, &diff->opts);
|
||||
@ -285,22 +283,18 @@ int git_diff_foreach(
|
||||
if (git_diff_delta__should_skip(&diff->opts, patch.delta))
|
||||
continue;
|
||||
|
||||
if (!(error = diff_patch_init_from_diff(&patch, diff, idx))) {
|
||||
if ((error = diff_patch_init_from_diff(&patch, diff, idx)) < 0)
|
||||
break;
|
||||
|
||||
error = diff_patch_file_callback(&patch, &xo.output);
|
||||
if (!(error = diff_patch_invoke_file_callback(&patch, &xo.output)))
|
||||
error = diff_patch_generate(&patch, &xo.output);
|
||||
|
||||
if (!error)
|
||||
error = diff_patch_generate(&patch, &xo.output);
|
||||
git_patch_free(&patch);
|
||||
|
||||
git_patch_free(&patch);
|
||||
}
|
||||
|
||||
if (error < 0)
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
giterr_clear(); /* don't leave error message set invalidly */
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -332,14 +326,11 @@ static int diff_single_generate(diff_patch_with_delta *pd, git_xdiff_output *xo)
|
||||
!(patch->ofile.opts_flags & GIT_DIFF_INCLUDE_UNMODIFIED))
|
||||
return error;
|
||||
|
||||
error = diff_patch_file_callback(patch, (git_diff_output *)xo);
|
||||
error = diff_patch_invoke_file_callback(patch, (git_diff_output *)xo);
|
||||
|
||||
if (!error)
|
||||
error = diff_patch_generate(patch, (git_diff_output *)xo);
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
giterr_clear(); /* don't leave error message set invalidly */
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -424,9 +415,7 @@ int git_diff_blobs(
|
||||
diff_patch_with_delta pd;
|
||||
git_xdiff_output xo;
|
||||
|
||||
memset(&pd, 0, sizeof(pd));
|
||||
memset(&xo, 0, sizeof(xo));
|
||||
|
||||
diff_output_init(
|
||||
&xo.output, opts, file_cb, hunk_cb, data_cb, payload);
|
||||
git_xdiff_init(&xo, opts);
|
||||
@ -436,6 +425,7 @@ int git_diff_blobs(
|
||||
else if (!new_path && old_path)
|
||||
new_path = old_path;
|
||||
|
||||
memset(&pd, 0, sizeof(pd));
|
||||
error = diff_patch_from_blobs(
|
||||
&pd, &xo, old_blob, old_path, new_blob, new_path, opts);
|
||||
|
||||
@ -463,7 +453,6 @@ int git_patch_from_blobs(
|
||||
return -1;
|
||||
|
||||
memset(&xo, 0, sizeof(xo));
|
||||
|
||||
diff_output_to_patch(&xo.output, &pd->patch);
|
||||
git_xdiff_init(&xo, opts);
|
||||
|
||||
@ -536,9 +525,7 @@ int git_diff_blob_to_buffer(
|
||||
diff_patch_with_delta pd;
|
||||
git_xdiff_output xo;
|
||||
|
||||
memset(&pd, 0, sizeof(pd));
|
||||
memset(&xo, 0, sizeof(xo));
|
||||
|
||||
diff_output_init(
|
||||
&xo.output, opts, file_cb, hunk_cb, data_cb, payload);
|
||||
git_xdiff_init(&xo, opts);
|
||||
@ -548,6 +535,7 @@ int git_diff_blob_to_buffer(
|
||||
else if (!buf_path && old_path)
|
||||
buf_path = old_path;
|
||||
|
||||
memset(&pd, 0, sizeof(pd));
|
||||
error = diff_patch_from_blob_and_buffer(
|
||||
&pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts);
|
||||
|
||||
@ -576,7 +564,6 @@ int git_patch_from_blob_and_buffer(
|
||||
return -1;
|
||||
|
||||
memset(&xo, 0, sizeof(xo));
|
||||
|
||||
diff_output_to_patch(&xo.output, &pd->patch);
|
||||
git_xdiff_init(&xo, opts);
|
||||
|
||||
@ -622,17 +609,18 @@ int git_patch_from_diff(
|
||||
if ((error = diff_patch_alloc_from_diff(&patch, diff, idx)) < 0)
|
||||
return error;
|
||||
|
||||
memset(&xo, 0, sizeof(xo));
|
||||
diff_output_to_patch(&xo.output, patch);
|
||||
git_xdiff_init(&xo, &diff->opts);
|
||||
|
||||
error = diff_patch_file_callback(patch, &xo.output);
|
||||
error = diff_patch_invoke_file_callback(patch, &xo.output);
|
||||
|
||||
if (!error)
|
||||
error = diff_patch_generate(patch, &xo.output);
|
||||
|
||||
if (!error) {
|
||||
/* if cumulative diff size is < 0.5 total size, flatten the patch */
|
||||
/* unload the file content */
|
||||
/* TODO: if cumulative diff size is < 0.5 total size, flatten patch */
|
||||
/* TODO: and unload the file content */
|
||||
}
|
||||
|
||||
if (error || !patch_ptr)
|
||||
@ -640,8 +628,6 @@ int git_patch_from_diff(
|
||||
else
|
||||
*patch_ptr = patch;
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
giterr_clear(); /* don't leave error message set invalidly */
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -905,7 +891,7 @@ static int diff_patch_line_cb(
|
||||
GIT_UNUSED(hunk_);
|
||||
|
||||
hunk = git_array_last(patch->hunks);
|
||||
GITERR_CHECK_ALLOC(hunk);
|
||||
assert(hunk); /* programmer error if no hunk is available */
|
||||
|
||||
line = git_array_alloc(patch->lines);
|
||||
GITERR_CHECK_ALLOC(line);
|
||||
|
||||
@ -89,12 +89,6 @@ char git_diff_status_char(git_delta_t status)
|
||||
return code;
|
||||
}
|
||||
|
||||
static int callback_error(void)
|
||||
{
|
||||
giterr_clear();
|
||||
return GIT_EUSER;
|
||||
}
|
||||
|
||||
static int diff_print_one_name_only(
|
||||
const git_diff_delta *delta, float progress, void *data)
|
||||
{
|
||||
@ -108,19 +102,16 @@ static int diff_print_one_name_only(
|
||||
return 0;
|
||||
|
||||
git_buf_clear(out);
|
||||
|
||||
if (git_buf_puts(out, delta->new_file.path) < 0 ||
|
||||
git_buf_putc(out, '\n'))
|
||||
git_buf_puts(out, delta->new_file.path);
|
||||
git_buf_putc(out, '\n');
|
||||
if (git_buf_oom(out))
|
||||
return -1;
|
||||
|
||||
pi->line.origin = GIT_DIFF_LINE_FILE_HDR;
|
||||
pi->line.content = git_buf_cstr(out);
|
||||
pi->line.content_len = git_buf_len(out);
|
||||
|
||||
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
|
||||
return callback_error();
|
||||
|
||||
return 0;
|
||||
return pi->print_cb(delta, NULL, &pi->line, pi->payload);
|
||||
}
|
||||
|
||||
static int diff_print_one_name_status(
|
||||
@ -154,7 +145,6 @@ static int diff_print_one_name_status(
|
||||
git_buf_printf(out, "%c\t%s%c\n", code, delta->old_file.path, old_suffix);
|
||||
else
|
||||
git_buf_printf(out, "%c\t%s\n", code, delta->old_file.path);
|
||||
|
||||
if (git_buf_oom(out))
|
||||
return -1;
|
||||
|
||||
@ -162,10 +152,7 @@ static int diff_print_one_name_status(
|
||||
pi->line.content = git_buf_cstr(out);
|
||||
pi->line.content_len = git_buf_len(out);
|
||||
|
||||
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
|
||||
return callback_error();
|
||||
|
||||
return 0;
|
||||
return pi->print_cb(delta, NULL, &pi->line, pi->payload);
|
||||
}
|
||||
|
||||
static int diff_print_one_raw(
|
||||
@ -208,10 +195,7 @@ static int diff_print_one_raw(
|
||||
pi->line.content = git_buf_cstr(out);
|
||||
pi->line.content_len = git_buf_len(out);
|
||||
|
||||
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
|
||||
return callback_error();
|
||||
|
||||
return 0;
|
||||
return pi->print_cb(delta, NULL, &pi->line, pi->payload);
|
||||
}
|
||||
|
||||
static int diff_print_oid_range(
|
||||
@ -238,10 +222,7 @@ static int diff_print_oid_range(
|
||||
git_buf_printf(out, "index %s..%s\n", start_oid, end_oid);
|
||||
}
|
||||
|
||||
if (git_buf_oom(out))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return git_buf_oom(out) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int diff_delta_format_with_paths(
|
||||
@ -285,8 +266,7 @@ int git_diff_delta__format_file_header(
|
||||
git_buf_printf(out, "diff --git %s%s %s%s\n",
|
||||
oldpfx, delta->old_file.path, newpfx, delta->new_file.path);
|
||||
|
||||
if (diff_print_oid_range(out, delta, oid_strlen) < 0)
|
||||
return -1;
|
||||
GITERR_CHECK_ERROR(diff_print_oid_range(out, delta, oid_strlen));
|
||||
|
||||
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0)
|
||||
diff_delta_format_with_paths(
|
||||
@ -298,6 +278,7 @@ int git_diff_delta__format_file_header(
|
||||
static int diff_print_patch_file(
|
||||
const git_diff_delta *delta, float progress, void *data)
|
||||
{
|
||||
int error;
|
||||
diff_print_info *pi = data;
|
||||
const char *oldpfx =
|
||||
pi->diff ? pi->diff->opts.old_prefix : DIFF_OLD_PREFIX_DEFAULT;
|
||||
@ -313,36 +294,33 @@ static int diff_print_patch_file(
|
||||
(pi->flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) == 0))
|
||||
return 0;
|
||||
|
||||
if (git_diff_delta__format_file_header(
|
||||
pi->buf, delta, oldpfx, newpfx, pi->oid_strlen) < 0)
|
||||
return -1;
|
||||
if ((error = git_diff_delta__format_file_header(
|
||||
pi->buf, delta, oldpfx, newpfx, pi->oid_strlen)) < 0)
|
||||
return error;
|
||||
|
||||
pi->line.origin = GIT_DIFF_LINE_FILE_HDR;
|
||||
pi->line.content = git_buf_cstr(pi->buf);
|
||||
pi->line.content_len = git_buf_len(pi->buf);
|
||||
|
||||
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
|
||||
return callback_error();
|
||||
if ((error = pi->print_cb(delta, NULL, &pi->line, pi->payload)) != 0)
|
||||
return error;
|
||||
|
||||
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0)
|
||||
return 0;
|
||||
|
||||
git_buf_clear(pi->buf);
|
||||
|
||||
if (diff_delta_format_with_paths(
|
||||
if ((error = diff_delta_format_with_paths(
|
||||
pi->buf, delta, oldpfx, newpfx,
|
||||
"Binary files %s%s and %s%s differ\n") < 0)
|
||||
return -1;
|
||||
"Binary files %s%s and %s%s differ\n")) < 0)
|
||||
return error;
|
||||
|
||||
pi->line.origin = GIT_DIFF_LINE_BINARY;
|
||||
pi->line.content = git_buf_cstr(pi->buf);
|
||||
pi->line.content_len = git_buf_len(pi->buf);
|
||||
pi->line.num_lines = 1;
|
||||
|
||||
if (pi->print_cb(delta, NULL, &pi->line, pi->payload))
|
||||
return callback_error();
|
||||
|
||||
return 0;
|
||||
return pi->print_cb(delta, NULL, &pi->line, pi->payload);
|
||||
}
|
||||
|
||||
static int diff_print_patch_hunk(
|
||||
@ -359,10 +337,7 @@ static int diff_print_patch_hunk(
|
||||
pi->line.content = h->header;
|
||||
pi->line.content_len = h->header_len;
|
||||
|
||||
if (pi->print_cb(d, h, &pi->line, pi->payload))
|
||||
return callback_error();
|
||||
|
||||
return 0;
|
||||
return pi->print_cb(d, h, &pi->line, pi->payload);
|
||||
}
|
||||
|
||||
static int diff_print_patch_line(
|
||||
@ -376,10 +351,7 @@ static int diff_print_patch_line(
|
||||
if (S_ISDIR(delta->new_file.mode))
|
||||
return 0;
|
||||
|
||||
if (pi->print_cb(delta, hunk, line, pi->payload))
|
||||
return callback_error();
|
||||
|
||||
return 0;
|
||||
return pi->print_cb(delta, hunk, line, pi->payload);
|
||||
}
|
||||
|
||||
/* print a git_diff to an output callback */
|
||||
@ -421,9 +393,14 @@ int git_diff_print(
|
||||
|
||||
if (!(error = diff_print_info_init(
|
||||
&pi, &buf, diff, format, print_cb, payload)))
|
||||
{
|
||||
error = git_diff_foreach(
|
||||
diff, print_file, print_hunk, print_line, &pi);
|
||||
|
||||
if (error) /* make sure error message is set */
|
||||
giterr_set_after_callback_function(error, "git_diff_print");
|
||||
}
|
||||
|
||||
git_buf_free(&buf);
|
||||
|
||||
return error;
|
||||
@ -444,10 +421,15 @@ int git_patch_print(
|
||||
if (!(error = diff_print_info_init(
|
||||
&pi, &temp, git_patch__diff(patch),
|
||||
GIT_DIFF_FORMAT_PATCH, print_cb, payload)))
|
||||
{
|
||||
error = git_patch__invoke_callbacks(
|
||||
patch, diff_print_patch_file, diff_print_patch_hunk,
|
||||
diff_print_patch_line, &pi);
|
||||
|
||||
if (error) /* make sure error message is set */
|
||||
giterr_set_after_callback_function(error, "git_patch_print");
|
||||
}
|
||||
|
||||
git_buf_free(&temp);
|
||||
|
||||
return error;
|
||||
@ -478,15 +460,12 @@ int git_patch_to_str(
|
||||
int error;
|
||||
git_buf output = GIT_BUF_INIT;
|
||||
|
||||
error = git_patch_print(patch, diff_print_to_buffer_cb, &output);
|
||||
|
||||
/* GIT_EUSER means git_buf_put in print_to_buffer_cb returned -1,
|
||||
* meaning a memory allocation failure, so just map to -1...
|
||||
*/
|
||||
if (error == GIT_EUSER)
|
||||
error = -1;
|
||||
|
||||
*string = git_buf_detach(&output);
|
||||
if (!(error = git_patch_print(patch, diff_print_to_buffer_cb, &output)))
|
||||
*string = git_buf_detach(&output);
|
||||
else {
|
||||
git_buf_free(&output);
|
||||
*string = NULL;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "hashsig.h"
|
||||
#include "path.h"
|
||||
#include "fileops.h"
|
||||
#include "config.h"
|
||||
|
||||
static git_diff_delta *diff_delta__dup(
|
||||
const git_diff_delta *d, git_pool *pool)
|
||||
@ -208,9 +209,7 @@ int git_diff_merge(git_diff *onto, const git_diff *from)
|
||||
git_pool_strdup_safe(&onto->pool, onto->opts.new_prefix);
|
||||
}
|
||||
|
||||
git_vector_foreach(&onto_new, i, delta)
|
||||
git__free(delta);
|
||||
git_vector_free(&onto_new);
|
||||
git_vector_free_deep(&onto_new);
|
||||
git_pool_clear(&onto_pool);
|
||||
|
||||
return error;
|
||||
@ -281,28 +280,22 @@ static int normalize_find_opts(
|
||||
git_repository_config__weakptr(&cfg, diff->repo) < 0)
|
||||
return -1;
|
||||
|
||||
if (given) {
|
||||
if (given)
|
||||
memcpy(opts, given, sizeof(*opts));
|
||||
} else {
|
||||
GIT_INIT_STRUCTURE(opts, GIT_DIFF_FIND_OPTIONS_VERSION);
|
||||
}
|
||||
|
||||
if (!given ||
|
||||
(given->flags & GIT_DIFF_FIND_ALL) == GIT_DIFF_FIND_BY_CONFIG)
|
||||
{
|
||||
const char *val = NULL;
|
||||
const char *rule =
|
||||
git_config__get_string_force(cfg, "diff.renames", "true");
|
||||
int boolval;
|
||||
|
||||
if (git_config_get_string(&val, cfg, "diff.renames") < 0)
|
||||
giterr_clear();
|
||||
else if (val) {
|
||||
int boolval;
|
||||
if (!git__parse_bool(&boolval, val) && !boolval) {
|
||||
/* do nothing */
|
||||
} else if (!strcasecmp(val, "copies") || !strcasecmp(val, "copy"))
|
||||
opts->flags |= (GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES);
|
||||
else
|
||||
opts->flags |= GIT_DIFF_FIND_RENAMES;
|
||||
}
|
||||
if (!git__parse_bool(&boolval, rule) && !boolval)
|
||||
/* don't set FIND_RENAMES if bool value is false */;
|
||||
else if (!strcasecmp(rule, "copies") || !strcasecmp(rule, "copy"))
|
||||
opts->flags |= GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES;
|
||||
else
|
||||
opts->flags |= GIT_DIFF_FIND_RENAMES;
|
||||
}
|
||||
|
||||
/* some flags imply others */
|
||||
@ -343,14 +336,11 @@ static int normalize_find_opts(
|
||||
#undef USE_DEFAULT
|
||||
|
||||
if (!opts->rename_limit) {
|
||||
int32_t limit = 0;
|
||||
opts->rename_limit = git_config__get_int_force(
|
||||
cfg, "diff.renamelimit", DEFAULT_RENAME_LIMIT);
|
||||
|
||||
opts->rename_limit = DEFAULT_RENAME_LIMIT;
|
||||
|
||||
if (git_config_get_int32(&limit, cfg, "diff.renameLimit") < 0)
|
||||
giterr_clear();
|
||||
else if (limit > 0)
|
||||
opts->rename_limit = limit;
|
||||
if (opts->rename_limit <= 0)
|
||||
opts->rename_limit = DEFAULT_RENAME_LIMIT;
|
||||
}
|
||||
|
||||
/* assign the internal metric with whitespace flag as payload */
|
||||
@ -450,9 +440,7 @@ static int apply_splits_and_deletes(
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
git_vector_foreach(&onto, i, delta)
|
||||
git__free(delta);
|
||||
git_vector_free(&onto);
|
||||
git_vector_free_deep(&onto);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -824,11 +812,11 @@ int git_diff_find_similar(
|
||||
int error = 0, result;
|
||||
uint16_t similarity;
|
||||
git_diff_delta *src, *tgt;
|
||||
git_diff_find_options opts;
|
||||
git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
|
||||
size_t num_deltas, num_srcs = 0, num_tgts = 0;
|
||||
size_t tried_srcs = 0, tried_tgts = 0;
|
||||
size_t num_rewrites = 0, num_updates = 0, num_bumped = 0;
|
||||
void **sigcache; /* cache of similarity metric file signatures */
|
||||
void **sigcache = NULL; /* cache of similarity metric file signatures */
|
||||
diff_find_match *tgt2src = NULL;
|
||||
diff_find_match *src2tgt = NULL;
|
||||
diff_find_match *tgt2src_copy = NULL;
|
||||
@ -838,15 +826,15 @@ int git_diff_find_similar(
|
||||
if ((error = normalize_find_opts(diff, &opts, given_opts)) < 0)
|
||||
return error;
|
||||
|
||||
/* No flags set; nothing to do */
|
||||
if ((opts.flags & GIT_DIFF_FIND_ALL) == 0)
|
||||
return 0;
|
||||
|
||||
num_deltas = diff->deltas.length;
|
||||
|
||||
/* TODO: maybe abort if deltas.length > rename_limit ??? */
|
||||
if (!git__is_uint32(num_deltas))
|
||||
return 0;
|
||||
goto cleanup;
|
||||
|
||||
/* No flags set; nothing to do */
|
||||
if ((opts.flags & GIT_DIFF_FIND_ALL) == 0)
|
||||
goto cleanup;
|
||||
|
||||
sigcache = git__calloc(num_deltas * 2, sizeof(void *));
|
||||
GITERR_CHECK_ALLOC(sigcache);
|
||||
@ -1121,11 +1109,13 @@ cleanup:
|
||||
git__free(src2tgt);
|
||||
git__free(tgt2src_copy);
|
||||
|
||||
for (t = 0; t < num_deltas * 2; ++t) {
|
||||
if (sigcache[t] != NULL)
|
||||
opts.metric->free_signature(sigcache[t], opts.metric->payload);
|
||||
if (sigcache) {
|
||||
for (t = 0; t < num_deltas * 2; ++t) {
|
||||
if (sigcache[t] != NULL)
|
||||
opts.metric->free_signature(sigcache[t], opts.metric->payload);
|
||||
}
|
||||
git__free(sigcache);
|
||||
}
|
||||
git__free(sigcache);
|
||||
|
||||
if (!given_opts || !given_opts->metric)
|
||||
git__free(opts.metric);
|
||||
|
||||
@ -28,25 +28,29 @@ static int git_xdiff_parse_hunk(git_diff_hunk *hunk, const char *header)
|
||||
{
|
||||
/* expect something of the form "@@ -%d[,%d] +%d[,%d] @@" */
|
||||
if (*header != '@')
|
||||
return -1;
|
||||
goto fail;
|
||||
if (git_xdiff_scan_int(&header, &hunk->old_start) < 0)
|
||||
return -1;
|
||||
goto fail;
|
||||
if (*header == ',') {
|
||||
if (git_xdiff_scan_int(&header, &hunk->old_lines) < 0)
|
||||
return -1;
|
||||
goto fail;
|
||||
} else
|
||||
hunk->old_lines = 1;
|
||||
if (git_xdiff_scan_int(&header, &hunk->new_start) < 0)
|
||||
return -1;
|
||||
goto fail;
|
||||
if (*header == ',') {
|
||||
if (git_xdiff_scan_int(&header, &hunk->new_lines) < 0)
|
||||
return -1;
|
||||
goto fail;
|
||||
} else
|
||||
hunk->new_lines = 1;
|
||||
if (hunk->old_start < 0 || hunk->new_start < 0)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
giterr_set(GITERR_INVALID, "Malformed hunk header from xdiff");
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@ -122,8 +126,9 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len)
|
||||
info->hunk.header[info->hunk.header_len] = '\0';
|
||||
|
||||
if (output->hunk_cb != NULL &&
|
||||
output->hunk_cb(delta, &info->hunk, output->payload))
|
||||
output->error = GIT_EUSER;
|
||||
(output->error = output->hunk_cb(
|
||||
delta, &info->hunk, output->payload)))
|
||||
return output->error;
|
||||
|
||||
info->old_lineno = info->hunk.old_start;
|
||||
info->new_lineno = info->hunk.new_start;
|
||||
@ -146,10 +151,9 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len)
|
||||
output->error = diff_update_lines(
|
||||
info, &line, bufs[1].ptr, bufs[1].size);
|
||||
|
||||
if (!output->error &&
|
||||
output->data_cb != NULL &&
|
||||
output->data_cb(delta, &info->hunk, &line, output->payload))
|
||||
output->error = GIT_EUSER;
|
||||
if (!output->error && output->data_cb != NULL)
|
||||
output->error = output->data_cb(
|
||||
delta, &info->hunk, &line, output->payload);
|
||||
}
|
||||
|
||||
if (len == 3 && !output->error) {
|
||||
@ -168,10 +172,9 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len)
|
||||
output->error = diff_update_lines(
|
||||
info, &line, bufs[2].ptr, bufs[2].size);
|
||||
|
||||
if (!output->error &&
|
||||
output->data_cb != NULL &&
|
||||
output->data_cb(delta, &info->hunk, &line, output->payload))
|
||||
output->error = GIT_EUSER;
|
||||
if (!output->error && output->data_cb != NULL)
|
||||
output->error = output->data_cb(
|
||||
delta, &info->hunk, &line, output->payload);
|
||||
}
|
||||
|
||||
return output->error;
|
||||
@ -219,11 +222,9 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts)
|
||||
|
||||
xo->output.diff_cb = git_xdiff;
|
||||
|
||||
memset(&xo->config, 0, sizeof(xo->config));
|
||||
xo->config.ctxlen = opts ? opts->context_lines : 3;
|
||||
xo->config.interhunkctxlen = opts ? opts->interhunk_lines : 0;
|
||||
|
||||
memset(&xo->params, 0, sizeof(xo->params));
|
||||
if (flags & GIT_DIFF_IGNORE_WHITESPACE)
|
||||
xo->params.flags |= XDF_WHITESPACE_FLAGS;
|
||||
if (flags & GIT_DIFF_IGNORE_WHITESPACE_CHANGE)
|
||||
@ -236,6 +237,5 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts)
|
||||
if (flags & GIT_DIFF_MINIMAL)
|
||||
xo->params.flags |= XDF_NEED_MINIMAL;
|
||||
|
||||
memset(&xo->callback, 0, sizeof(xo->callback));
|
||||
xo->callback.outf = git_xdiff_cb;
|
||||
}
|
||||
|
||||
45
src/errors.c
45
src/errors.c
@ -23,7 +23,8 @@ static void set_error(int error_class, char *string)
|
||||
{
|
||||
git_error *error = &GIT_GLOBAL->error_t;
|
||||
|
||||
git__free(error->message);
|
||||
if (error->message != string)
|
||||
git__free(error->message);
|
||||
|
||||
error->message = string;
|
||||
error->klass = error_class;
|
||||
@ -103,8 +104,10 @@ int giterr_set_regex(const regex_t *regex, int error_code)
|
||||
|
||||
void giterr_clear(void)
|
||||
{
|
||||
set_error(0, NULL);
|
||||
GIT_GLOBAL->last_error = NULL;
|
||||
if (GIT_GLOBAL->last_error != NULL) {
|
||||
set_error(0, NULL);
|
||||
GIT_GLOBAL->last_error = NULL;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
#ifdef GIT_WIN32
|
||||
@ -134,3 +137,39 @@ const git_error *giterr_last(void)
|
||||
{
|
||||
return GIT_GLOBAL->last_error;
|
||||
}
|
||||
|
||||
int giterr_capture(git_error_state *state, int error_code)
|
||||
{
|
||||
state->error_code = error_code;
|
||||
if (error_code)
|
||||
giterr_detach(&state->error_msg);
|
||||
return error_code;
|
||||
}
|
||||
|
||||
int giterr_restore(git_error_state *state)
|
||||
{
|
||||
if (state && state->error_code && state->error_msg.message)
|
||||
set_error(state->error_msg.klass, state->error_msg.message);
|
||||
else
|
||||
giterr_clear();
|
||||
|
||||
return state ? state->error_code : 0;
|
||||
}
|
||||
|
||||
int giterr_system_last(void)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
return GetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
void giterr_system_set(int code)
|
||||
{
|
||||
#ifdef GIT_WIN32
|
||||
SetLastError(code);
|
||||
#else
|
||||
errno = code;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ cleanup:
|
||||
int git_fetch_negotiate(git_remote *remote)
|
||||
{
|
||||
git_transport *t = remote->transport;
|
||||
|
||||
|
||||
if (filter_wants(remote) < 0) {
|
||||
giterr_set(GITERR_NET, "Failed to filter the reference list for wants");
|
||||
return -1;
|
||||
@ -128,9 +128,9 @@ int git_fetch_download_pack(git_remote *remote)
|
||||
{
|
||||
git_transport *t = remote->transport;
|
||||
|
||||
if(!remote->need_pack)
|
||||
if (!remote->need_pack)
|
||||
return 0;
|
||||
|
||||
return t->download_pack(t, remote->repo, &remote->stats,
|
||||
remote->callbacks.transfer_progress, remote->callbacks.payload);
|
||||
remote->callbacks.transfer_progress, remote->callbacks.payload);
|
||||
}
|
||||
|
||||
@ -260,8 +260,8 @@ int git_repository_fetchhead_foreach(git_repository *repo,
|
||||
while ((line = git__strsep(&buffer, "\n")) != NULL) {
|
||||
++line_num;
|
||||
|
||||
if ((error = fetchhead_ref_parse(&oid, &is_merge, &name, &remote_url,
|
||||
line, line_num)) < 0)
|
||||
if ((error = fetchhead_ref_parse(
|
||||
&oid, &is_merge, &name, &remote_url, line, line_num)) < 0)
|
||||
goto done;
|
||||
|
||||
if (git_buf_len(&name) > 0)
|
||||
@ -269,8 +269,9 @@ int git_repository_fetchhead_foreach(git_repository *repo,
|
||||
else
|
||||
ref_name = NULL;
|
||||
|
||||
if ((cb(ref_name, remote_url, &oid, is_merge, payload)) != 0) {
|
||||
error = GIT_EUSER;
|
||||
error = cb(ref_name, remote_url, &oid, is_merge, payload);
|
||||
if (error) {
|
||||
giterr_set_after_callback(error);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,7 +403,6 @@ typedef struct {
|
||||
const char *base;
|
||||
size_t baselen;
|
||||
uint32_t flags;
|
||||
int error;
|
||||
int depth;
|
||||
} futils__rmdir_data;
|
||||
|
||||
@ -447,8 +446,8 @@ static int futils__rm_first_parent(git_buf *path, const char *ceiling)
|
||||
|
||||
static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
|
||||
{
|
||||
int error = 0;
|
||||
futils__rmdir_data *data = opaque;
|
||||
int error = data->error;
|
||||
struct stat st;
|
||||
|
||||
if (data->depth > FUTILS_MAX_DEPTH)
|
||||
@ -474,13 +473,14 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
|
||||
data->depth++;
|
||||
|
||||
error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data);
|
||||
if (error < 0)
|
||||
return (error == GIT_EUSER) ? data->error : error;
|
||||
|
||||
data->depth--;
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0)
|
||||
return data->error;
|
||||
return error;
|
||||
|
||||
if ((error = p_rmdir(path->ptr)) < 0) {
|
||||
if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 &&
|
||||
@ -499,28 +499,23 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
|
||||
else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0)
|
||||
error = futils__error_cannot_rmdir(path->ptr, "still present");
|
||||
|
||||
data->error = error;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
|
||||
{
|
||||
futils__rmdir_data *data = opaque;
|
||||
int error;
|
||||
int error = 0;
|
||||
|
||||
if (git_buf_len(path) <= data->baselen)
|
||||
return GIT_ITEROVER;
|
||||
error = GIT_ITEROVER;
|
||||
|
||||
error = p_rmdir(git_buf_cstr(path));
|
||||
|
||||
if (error) {
|
||||
else if (p_rmdir(git_buf_cstr(path)) < 0) {
|
||||
int en = errno;
|
||||
|
||||
if (en == ENOENT || en == ENOTDIR) {
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
/* do nothing */
|
||||
} else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) {
|
||||
giterr_clear();
|
||||
error = GIT_ITEROVER;
|
||||
} else {
|
||||
error = git_path_set_error(errno, git_buf_cstr(path), "rmdir");
|
||||
@ -535,12 +530,13 @@ int git_futils_rmdir_r(
|
||||
{
|
||||
int error;
|
||||
git_buf fullpath = GIT_BUF_INIT;
|
||||
futils__rmdir_data data = { 0 };
|
||||
futils__rmdir_data data;
|
||||
|
||||
/* build path and find "root" where we should start calling mkdir */
|
||||
if (git_path_join_unrooted(&fullpath, path, base, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.base = base ? base : "";
|
||||
data.baselen = base ? strlen(base) : 0;
|
||||
data.flags = flags;
|
||||
@ -548,12 +544,13 @@ int git_futils_rmdir_r(
|
||||
error = futils__rmdir_recurs_foreach(&data, &fullpath);
|
||||
|
||||
/* remove now-empty parents if requested */
|
||||
if (!error && (flags & GIT_RMDIR_EMPTY_PARENTS) != 0) {
|
||||
if (!error && (flags & GIT_RMDIR_EMPTY_PARENTS) != 0)
|
||||
error = git_path_walk_up(
|
||||
&fullpath, base, futils__rmdir_empty_parent, &data);
|
||||
|
||||
if (error == GIT_ITEROVER)
|
||||
error = 0;
|
||||
if (error == GIT_ITEROVER) {
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
}
|
||||
|
||||
git_buf_free(&fullpath);
|
||||
@ -618,6 +615,8 @@ static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = {
|
||||
git_futils_guess_template_dirs,
|
||||
};
|
||||
|
||||
static int git_futils__dirs_shutdown_set = 0;
|
||||
|
||||
void git_futils_dirs_global_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
@ -634,8 +633,6 @@ int git_futils_dirs_global_init(void)
|
||||
for (i = 0; !error && i < GIT_FUTILS_DIR__MAX; i++)
|
||||
error = git_futils_dirs_get(&path, i);
|
||||
|
||||
git__on_shutdown(git_futils_dirs_global_shutdown);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -655,9 +652,16 @@ int git_futils_dirs_get(const git_buf **out, git_futils_dir_t which)
|
||||
|
||||
GITERR_CHECK_ERROR(git_futils_check_selector(which));
|
||||
|
||||
if (!git_buf_len(&git_futils__dirs[which]))
|
||||
if (!git_buf_len(&git_futils__dirs[which])) {
|
||||
/* prepare shutdown if we're going to need it */
|
||||
if (!git_futils__dirs_shutdown_set) {
|
||||
git__on_shutdown(git_futils_dirs_global_shutdown);
|
||||
git_futils__dirs_shutdown_set = 1;
|
||||
}
|
||||
|
||||
GITERR_CHECK_ERROR(
|
||||
git_futils__dir_guess[which](&git_futils__dirs[which]));
|
||||
}
|
||||
|
||||
*out = &git_futils__dirs[which];
|
||||
return 0;
|
||||
@ -858,7 +862,6 @@ typedef struct {
|
||||
uint32_t flags;
|
||||
uint32_t mkdir_flags;
|
||||
mode_t dirmode;
|
||||
int error;
|
||||
} cp_r_info;
|
||||
|
||||
#define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10)
|
||||
@ -896,23 +899,21 @@ static int _cp_r_callback(void *ref, git_buf *from)
|
||||
from->ptr[git_path_basename_offset(from)] == '.')
|
||||
return 0;
|
||||
|
||||
if (git_buf_joinpath(
|
||||
&info->to, info->to_root, from->ptr + info->from_prefix) < 0) {
|
||||
error = -1;
|
||||
goto exit;
|
||||
}
|
||||
if ((error = git_buf_joinpath(
|
||||
&info->to, info->to_root, from->ptr + info->from_prefix)) < 0)
|
||||
return error;
|
||||
|
||||
if (!(error = git_path_lstat(info->to.ptr, &to_st)))
|
||||
exists = true;
|
||||
else if (error != GIT_ENOTFOUND)
|
||||
goto exit;
|
||||
return error;
|
||||
else {
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
}
|
||||
|
||||
if ((error = git_path_lstat(from->ptr, &from_st)) < 0)
|
||||
goto exit;
|
||||
return error;
|
||||
|
||||
if (S_ISDIR(from_st.st_mode)) {
|
||||
mode_t oldmode = info->dirmode;
|
||||
@ -926,17 +927,13 @@ static int _cp_r_callback(void *ref, git_buf *from)
|
||||
error = _cp_r_mkdir(info, from);
|
||||
|
||||
/* recurse onto target directory */
|
||||
if (!error && (!exists || S_ISDIR(to_st.st_mode))) {
|
||||
if (!error && (!exists || S_ISDIR(to_st.st_mode)))
|
||||
error = git_path_direach(from, 0, _cp_r_callback, info);
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
error = info->error;
|
||||
}
|
||||
|
||||
if (oldmode != 0)
|
||||
info->dirmode = oldmode;
|
||||
|
||||
goto exit;
|
||||
return error;
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
@ -946,8 +943,7 @@ static int _cp_r_callback(void *ref, git_buf *from)
|
||||
if (p_unlink(info->to.ptr) < 0) {
|
||||
giterr_set(GITERR_OS, "Cannot overwrite existing file '%s'",
|
||||
info->to.ptr);
|
||||
error = -1;
|
||||
goto exit;
|
||||
return GIT_EEXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -960,7 +956,7 @@ static int _cp_r_callback(void *ref, git_buf *from)
|
||||
/* Make container directory on demand if needed */
|
||||
if ((info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0 &&
|
||||
(error = _cp_r_mkdir(info, from)) < 0)
|
||||
goto exit;
|
||||
return error;
|
||||
|
||||
/* make symlink or regular file */
|
||||
if (S_ISLNK(from_st.st_mode))
|
||||
@ -974,8 +970,6 @@ static int _cp_r_callback(void *ref, git_buf *from)
|
||||
error = git_futils_cp(from->ptr, info->to.ptr, usemode);
|
||||
}
|
||||
|
||||
exit:
|
||||
info->error = error;
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -992,11 +986,11 @@ int git_futils_cp_r(
|
||||
if (git_buf_joinpath(&path, from, "") < 0) /* ensure trailing slash */
|
||||
return -1;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.to_root = to;
|
||||
info.flags = flags;
|
||||
info.dirmode = dirmode;
|
||||
info.from_prefix = path.size;
|
||||
info.error = 0;
|
||||
git_buf_init(&info.to, 0);
|
||||
|
||||
/* precalculate mkdir flags */
|
||||
@ -1018,9 +1012,6 @@ int git_futils_cp_r(
|
||||
git_buf_free(&path);
|
||||
git_buf_free(&info.to);
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
error = info.error;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@ -69,7 +69,7 @@ static void filter_registry_shutdown(void)
|
||||
return;
|
||||
|
||||
git_vector_foreach(®->filters, pos, fdef) {
|
||||
if (fdef->initialized && fdef->filter && fdef->filter->shutdown) {
|
||||
if (fdef->filter && fdef->filter->shutdown) {
|
||||
fdef->filter->shutdown(fdef->filter);
|
||||
fdef->initialized = false;
|
||||
}
|
||||
|
||||
@ -74,10 +74,12 @@ static int parse_ignore_file(
|
||||
#define push_ignore_file(R,IGN,S,B,F) \
|
||||
git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,parse_ignore_file,(IGN),(S))
|
||||
|
||||
static int push_one_ignore(void *ref, git_buf *path)
|
||||
static int push_one_ignore(void *payload, git_buf *path)
|
||||
{
|
||||
git_ignores *ign = (git_ignores *)ref;
|
||||
return push_ignore_file(ign->repo, ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
|
||||
git_ignores *ign = payload;
|
||||
|
||||
return push_ignore_file(
|
||||
ign->repo, ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
|
||||
}
|
||||
|
||||
static int get_internal_ignores(git_attr_file **ign, git_repository *repo)
|
||||
|
||||
31
src/index.c
31
src/index.c
@ -2036,11 +2036,12 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
|
||||
|
||||
error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data);
|
||||
|
||||
git_vector_sort(&entries);
|
||||
if (!error) {
|
||||
git_vector_sort(&entries);
|
||||
git_index_clear(index);
|
||||
git_vector_swap(&entries, &index->entries);
|
||||
}
|
||||
|
||||
git_index_clear(index);
|
||||
|
||||
git_vector_swap(&entries, &index->entries);
|
||||
git_vector_free(&entries);
|
||||
|
||||
return error;
|
||||
@ -2116,8 +2117,7 @@ int git_index_add_all(
|
||||
if (error > 0) /* return > 0 means skip this one */
|
||||
continue;
|
||||
if (error < 0) { /* return < 0 means abort */
|
||||
giterr_clear();
|
||||
error = GIT_EUSER;
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2204,11 +2204,8 @@ static int index_apply_to_all(
|
||||
error = 0;
|
||||
continue;
|
||||
}
|
||||
if (error < 0) { /* return < 0 means abort */
|
||||
giterr_clear();
|
||||
error = GIT_EUSER;
|
||||
if (error < 0) /* return < 0 means abort */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* index manipulation may alter entry, so don't depend on it */
|
||||
@ -2253,8 +2250,13 @@ int git_index_remove_all(
|
||||
git_index_matched_path_cb cb,
|
||||
void *payload)
|
||||
{
|
||||
return index_apply_to_all(
|
||||
int error = index_apply_to_all(
|
||||
index, INDEX_ACTION_REMOVE, pathspec, cb, payload);
|
||||
|
||||
if (error) /* make sure error is set if callback stopped iteration */
|
||||
giterr_set_after_callback(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_index_update_all(
|
||||
@ -2263,6 +2265,11 @@ int git_index_update_all(
|
||||
git_index_matched_path_cb cb,
|
||||
void *payload)
|
||||
{
|
||||
return index_apply_to_all(
|
||||
int error = index_apply_to_all(
|
||||
index, INDEX_ACTION_UPDATE, pathspec, cb, payload);
|
||||
|
||||
if (error) /* make sure error is set if callback stopped iteration */
|
||||
giterr_set_after_callback(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -386,12 +386,10 @@ on_error:
|
||||
|
||||
static int do_progress_callback(git_indexer *idx, git_transfer_progress *stats)
|
||||
{
|
||||
if (idx->progress_cb &&
|
||||
idx->progress_cb(stats, idx->progress_payload)) {
|
||||
giterr_clear();
|
||||
return GIT_EUSER;
|
||||
}
|
||||
|
||||
if (idx->progress_cb)
|
||||
return giterr_set_after_callback_function(
|
||||
idx->progress_cb(stats, idx->progress_payload),
|
||||
"indexer progress");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -443,8 +441,8 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
|
||||
processed = stats->indexed_objects;
|
||||
|
||||
if (git_filebuf_write(&idx->pack_file, data, size) < 0)
|
||||
return -1;
|
||||
if ((error = git_filebuf_write(&idx->pack_file, data, size)) < 0)
|
||||
return error;
|
||||
|
||||
hash_partially(idx, data, (int)size);
|
||||
|
||||
@ -452,12 +450,12 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
if (idx->opened_pack) {
|
||||
idx->pack->mwf.size += size;
|
||||
} else {
|
||||
if (open_pack(&idx->pack, idx->pack_file.path_lock) < 0)
|
||||
return -1;
|
||||
if ((error = open_pack(&idx->pack, idx->pack_file.path_lock)) < 0)
|
||||
return error;
|
||||
idx->opened_pack = 1;
|
||||
mwf = &idx->pack->mwf;
|
||||
if (git_mwindow_file_register(&idx->pack->mwf) < 0)
|
||||
return -1;
|
||||
if ((error = git_mwindow_file_register(&idx->pack->mwf)) < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!idx->parsed_header) {
|
||||
@ -466,8 +464,8 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
if ((unsigned)idx->pack->mwf.size < sizeof(struct git_pack_header))
|
||||
return 0;
|
||||
|
||||
if (parse_header(&idx->hdr, idx->pack) < 0)
|
||||
return -1;
|
||||
if ((error = parse_header(&idx->hdr, idx->pack)) < 0)
|
||||
return error;
|
||||
|
||||
idx->parsed_header = 1;
|
||||
idx->nr_objects = ntohl(hdr->hdr_entries);
|
||||
@ -497,7 +495,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
processed = stats->indexed_objects = 0;
|
||||
stats->total_objects = total_objects;
|
||||
|
||||
if ((error = do_progress_callback(idx, stats)) < 0)
|
||||
if ((error = do_progress_callback(idx, stats)) != 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -505,6 +503,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
|
||||
/* As the file grows any windows we try to use will be out of date */
|
||||
git_mwindow_free_all(mwf);
|
||||
|
||||
while (processed < idx->nr_objects) {
|
||||
git_packfile_stream *stream = &idx->stream;
|
||||
git_off_t entry_start = idx->off;
|
||||
@ -522,7 +521,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
return 0;
|
||||
}
|
||||
if (error < 0)
|
||||
return -1;
|
||||
goto on_error;
|
||||
|
||||
git_mwindow_close(&w);
|
||||
idx->entry_start = entry_start;
|
||||
@ -535,7 +534,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
return 0;
|
||||
}
|
||||
if (error < 0)
|
||||
return -1;
|
||||
goto on_error;
|
||||
|
||||
idx->have_delta = 1;
|
||||
} else {
|
||||
@ -544,9 +543,10 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
}
|
||||
|
||||
idx->have_stream = 1;
|
||||
if (git_packfile_stream_open(stream, idx->pack, idx->off) < 0)
|
||||
goto on_error;
|
||||
|
||||
error = git_packfile_stream_open(stream, idx->pack, idx->off);
|
||||
if (error < 0)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if (idx->have_delta) {
|
||||
@ -580,7 +580,7 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
|
||||
}
|
||||
stats->received_objects++;
|
||||
|
||||
if ((error = do_progress_callback(idx, stats)) < 0)
|
||||
if ((error = do_progress_callback(idx, stats)) != 0)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
@ -860,7 +860,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
|
||||
|
||||
/* Test for this before resolve_deltas(), as it plays with idx->off */
|
||||
if (idx->off < idx->pack->mwf.size - 20) {
|
||||
giterr_set(GITERR_INDEXER, "unexpected data at the end of the pack");
|
||||
giterr_set(GITERR_INDEXER, "Unexpected data at the end of the pack");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1007,30 +1007,20 @@ on_error:
|
||||
|
||||
void git_indexer_free(git_indexer *idx)
|
||||
{
|
||||
khiter_t k;
|
||||
unsigned int i;
|
||||
struct entry *e;
|
||||
struct delta_info *delta;
|
||||
|
||||
if (idx == NULL)
|
||||
return;
|
||||
|
||||
git_vector_foreach(&idx->objects, i, e)
|
||||
git__free(e);
|
||||
git_vector_free(&idx->objects);
|
||||
git_vector_free_deep(&idx->objects);
|
||||
|
||||
if (idx->pack) {
|
||||
for (k = kh_begin(idx->pack->idx_cache); k != kh_end(idx->pack->idx_cache); k++) {
|
||||
if (kh_exist(idx->pack->idx_cache, k))
|
||||
git__free(kh_value(idx->pack->idx_cache, k));
|
||||
}
|
||||
struct git_pack_entry *pentry;
|
||||
kh_foreach_value(
|
||||
idx->pack->idx_cache, pentry, { git__free(pentry); });
|
||||
|
||||
git_oidmap_free(idx->pack->idx_cache);
|
||||
}
|
||||
|
||||
git_vector_foreach(&idx->deltas, i, delta)
|
||||
git__free(delta);
|
||||
git_vector_free(&idx->deltas);
|
||||
git_vector_free_deep(&idx->deltas);
|
||||
git_packfile_free(idx->pack);
|
||||
git_filebuf_cleanup(&idx->pack_file);
|
||||
git__free(idx);
|
||||
|
||||
@ -920,12 +920,7 @@ static fs_iterator_frame *fs_iterator__alloc_frame(fs_iterator *fi)
|
||||
|
||||
static void fs_iterator__free_frame(fs_iterator_frame *ff)
|
||||
{
|
||||
size_t i;
|
||||
git_path_with_stat *path;
|
||||
|
||||
git_vector_foreach(&ff->entries, i, path)
|
||||
git__free(path);
|
||||
git_vector_free(&ff->entries);
|
||||
git_vector_free_deep(&ff->entries);
|
||||
git__free(ff);
|
||||
}
|
||||
|
||||
@ -991,9 +986,8 @@ static int fs_iterator__expand_dir(fs_iterator *fi)
|
||||
fi->base.start, fi->base.end, &ff->entries);
|
||||
|
||||
if (error < 0) {
|
||||
git_error last_error = {0};
|
||||
|
||||
giterr_detach(&last_error);
|
||||
git_error_state last_error = { 0 };
|
||||
giterr_capture(&last_error, error);
|
||||
|
||||
/* these callbacks may clear the error message */
|
||||
fs_iterator__free_frame(ff);
|
||||
@ -1001,12 +995,7 @@ static int fs_iterator__expand_dir(fs_iterator *fi)
|
||||
/* next time return value we skipped to */
|
||||
fi->base.flags &= ~GIT_ITERATOR_FIRST_ACCESS;
|
||||
|
||||
if (last_error.message) {
|
||||
giterr_set_str(last_error.klass, last_error.message);
|
||||
free(last_error.message);
|
||||
}
|
||||
|
||||
return error;
|
||||
return giterr_restore(&last_error);
|
||||
}
|
||||
|
||||
if (ff->entries.length == 0) {
|
||||
|
||||
30
src/merge.c
30
src/merge.c
@ -26,6 +26,7 @@
|
||||
#include "oid.h"
|
||||
#include "index.h"
|
||||
#include "filebuf.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "git2/types.h"
|
||||
#include "git2/repository.h"
|
||||
@ -253,7 +254,8 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_repository_mergehead_foreach(git_repository *repo,
|
||||
int git_repository_mergehead_foreach(
|
||||
git_repository *repo,
|
||||
git_repository_mergehead_foreach_cb cb,
|
||||
void *payload)
|
||||
{
|
||||
@ -285,8 +287,8 @@ int git_repository_mergehead_foreach(git_repository *repo,
|
||||
if ((error = git_oid_fromstr(&oid, line)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (cb(&oid, payload) != 0) {
|
||||
error = GIT_EUSER;
|
||||
if ((error = cb(&oid, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -1396,19 +1398,13 @@ static int merge_tree_normalize_opts(
|
||||
}
|
||||
|
||||
if (!opts->target_limit) {
|
||||
int32_t limit = 0;
|
||||
int limit = git_config__get_int_force(cfg, "merge.renamelimit", 0);
|
||||
|
||||
opts->target_limit = GIT_MERGE_TREE_TARGET_LIMIT;
|
||||
if (!limit)
|
||||
limit = git_config__get_int_force(cfg, "diff.renamelimit", 0);
|
||||
|
||||
if (git_config_get_int32(&limit, cfg, "merge.renameLimit") < 0) {
|
||||
giterr_clear();
|
||||
|
||||
if (git_config_get_int32(&limit, cfg, "diff.renameLimit") < 0)
|
||||
giterr_clear();
|
||||
}
|
||||
|
||||
if (limit > 0)
|
||||
opts->target_limit = limit;
|
||||
opts->target_limit = (limit <= 0) ?
|
||||
GIT_MERGE_TREE_TARGET_LIMIT : (unsigned int)limit;
|
||||
}
|
||||
|
||||
/* assign the internal metric with whitespace flag as payload */
|
||||
@ -2389,11 +2385,7 @@ done:
|
||||
git_index_set_caps(index_repo, index_repo_caps);
|
||||
|
||||
git_index_free(index_repo);
|
||||
|
||||
git_vector_foreach(&paths, i, path)
|
||||
git__free(path);
|
||||
|
||||
git_vector_free(&paths);
|
||||
git_vector_free_deep(&paths);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
19
src/notes.c
19
src/notes.c
@ -378,20 +378,11 @@ cleanup:
|
||||
|
||||
static int note_get_default_ref(const char **out, git_repository *repo)
|
||||
{
|
||||
int ret;
|
||||
git_config *cfg;
|
||||
int ret = git_repository_config__weakptr(&cfg, repo);
|
||||
|
||||
*out = NULL;
|
||||
|
||||
if (git_repository_config__weakptr(&cfg, repo) < 0)
|
||||
return -1;
|
||||
|
||||
ret = git_config_get_string(out, cfg, "core.notesRef");
|
||||
if (ret == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
*out = GIT_NOTES_DEFAULT_REF;
|
||||
return 0;
|
||||
}
|
||||
*out = (ret != 0) ? NULL : git_config__get_string_force(
|
||||
cfg, "core.notesref", GIT_NOTES_DEFAULT_REF);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -592,8 +583,8 @@ int git_note_foreach(
|
||||
return error;
|
||||
|
||||
while (!(error = git_note_next(¬e_id, &annotated_id, iter))) {
|
||||
if (note_cb(¬e_id, &annotated_id, payload)) {
|
||||
error = GIT_EUSER;
|
||||
if ((error = note_cb(¬e_id, &annotated_id, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -547,8 +547,7 @@ static int locate_object_short_oid(
|
||||
/* Explore directory to find a unique object matching short_oid */
|
||||
error = git_path_direach(
|
||||
object_location, 0, fn_locate_object_short_oid, &state);
|
||||
|
||||
if (error && error != GIT_EUSER)
|
||||
if (error < 0 && error != GIT_EAMBIGUOUS)
|
||||
return error;
|
||||
|
||||
if (!state.found)
|
||||
@ -696,7 +695,6 @@ struct foreach_state {
|
||||
size_t dir_len;
|
||||
git_odb_foreach_cb cb;
|
||||
void *data;
|
||||
int cb_error;
|
||||
};
|
||||
|
||||
GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
|
||||
@ -735,12 +733,8 @@ 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)) {
|
||||
state->cb_error = GIT_EUSER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return giterr_set_after_callback_function(
|
||||
state->cb(&oid, state->data), "git_odb_foreach");
|
||||
}
|
||||
|
||||
static int foreach_cb(void *_state, git_buf *path)
|
||||
@ -764,6 +758,8 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb
|
||||
|
||||
git_buf_sets(&buf, objects_dir);
|
||||
git_path_to_dir(&buf);
|
||||
if (git_buf_oom(&buf))
|
||||
return -1;
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.cb = cb;
|
||||
@ -774,7 +770,7 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb
|
||||
|
||||
git_buf_free(&buf);
|
||||
|
||||
return state.cb_error ? state.cb_error : error;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid *oid)
|
||||
|
||||
@ -190,31 +190,39 @@ static int packfile_sort__cb(const void *a_, const void *b_)
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int packfile_load__cb(void *_data, git_buf *path)
|
||||
static int packfile_load__cb(void *data, git_buf *path)
|
||||
{
|
||||
struct pack_backend *backend = (struct pack_backend *)_data;
|
||||
struct pack_backend *backend = data;
|
||||
struct git_pack_file *pack;
|
||||
const char *path_str = git_buf_cstr(path);
|
||||
size_t i, cmp_len = git_buf_len(path);
|
||||
int error;
|
||||
size_t i;
|
||||
|
||||
if (git__suffixcmp(path->ptr, ".idx") != 0)
|
||||
if (cmp_len <= strlen(".idx") || git__suffixcmp(path_str, ".idx") != 0)
|
||||
return 0; /* not an index */
|
||||
|
||||
cmp_len -= strlen(".idx");
|
||||
|
||||
for (i = 0; i < backend->packs.length; ++i) {
|
||||
struct git_pack_file *p = git_vector_get(&backend->packs, i);
|
||||
if (memcmp(p->pack_name, git_buf_cstr(path), git_buf_len(path) - strlen(".idx")) == 0)
|
||||
|
||||
if (memcmp(p->pack_name, path_str, cmp_len) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = git_packfile_alloc(&pack, path->ptr);
|
||||
if (error == GIT_ENOTFOUND)
|
||||
/* ignore missing .pack file as git does */
|
||||
return 0;
|
||||
else if (error < 0)
|
||||
return error;
|
||||
|
||||
return git_vector_insert(&backend->packs, pack);
|
||||
/* ignore missing .pack file as git does */
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!error)
|
||||
error = git_vector_insert(&backend->packs, pack);
|
||||
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
static int pack_entry_find_inner(
|
||||
@ -314,13 +322,12 @@ static int pack_entry_find_prefix(
|
||||
* Implement the git_odb_backend API calls
|
||||
*
|
||||
***********************************************************/
|
||||
static int pack_backend__refresh(git_odb_backend *_backend)
|
||||
static int pack_backend__refresh(git_odb_backend *backend_)
|
||||
{
|
||||
struct pack_backend *backend = (struct pack_backend *)_backend;
|
||||
|
||||
int error;
|
||||
struct stat st;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
struct pack_backend *backend = (struct pack_backend *)backend_;
|
||||
|
||||
if (backend->pack_folder == NULL)
|
||||
return 0;
|
||||
@ -334,12 +341,9 @@ static int pack_backend__refresh(git_odb_backend *_backend)
|
||||
error = git_path_direach(&path, 0, packfile_load__cb, backend);
|
||||
|
||||
git_buf_free(&path);
|
||||
|
||||
if (error < 0)
|
||||
return -1;
|
||||
|
||||
git_vector_sort(&backend->packs);
|
||||
return 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int pack_backend__read_header_internal(
|
||||
|
||||
@ -205,14 +205,18 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
|
||||
po = pb->object_list + pb->nr_objects;
|
||||
memset(po, 0x0, sizeof(*po));
|
||||
|
||||
if (git_odb_read_header(&po->size, &po->type, pb->odb, oid) < 0)
|
||||
return -1;
|
||||
if ((ret = git_odb_read_header(&po->size, &po->type, pb->odb, oid)) < 0)
|
||||
return ret;
|
||||
|
||||
pb->nr_objects++;
|
||||
git_oid_cpy(&po->id, oid);
|
||||
po->hash = name_hash(name);
|
||||
|
||||
pos = kh_put(oid, pb->object_ix, &po->id, &ret);
|
||||
if (ret < 0) {
|
||||
giterr_set_oom();
|
||||
return ret;
|
||||
}
|
||||
assert(ret != 0);
|
||||
kh_value(pb->object_ix, pos) = po;
|
||||
|
||||
@ -220,12 +224,17 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
|
||||
|
||||
if (pb->progress_cb) {
|
||||
double current_time = git__timer();
|
||||
if ((current_time - pb->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) {
|
||||
double elapsed = current_time - pb->last_progress_report_time;
|
||||
|
||||
if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
|
||||
pb->last_progress_report_time = current_time;
|
||||
if (pb->progress_cb(GIT_PACKBUILDER_ADDING_OBJECTS, pb->nr_objects, 0, pb->progress_cb_payload)) {
|
||||
giterr_clear();
|
||||
return GIT_EUSER;
|
||||
}
|
||||
|
||||
ret = pb->progress_cb(
|
||||
GIT_PACKBUILDER_ADDING_OBJECTS,
|
||||
pb->nr_objects, 0, pb->progress_cb_payload);
|
||||
|
||||
if (ret)
|
||||
return giterr_set_after_callback(ret);
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,8 +332,10 @@ static int write_object(git_buf *buf, git_packbuilder *pb, git_pobject *po)
|
||||
git_hash_update(&pb->ctx, data, size) < 0)
|
||||
goto on_error;
|
||||
|
||||
if (po->delta_data)
|
||||
if (po->delta_data) {
|
||||
git__free(po->delta_data);
|
||||
po->delta_data = NULL;
|
||||
}
|
||||
|
||||
git_odb_object_free(obj);
|
||||
git_buf_free(&zbuf);
|
||||
@ -603,6 +614,15 @@ static int write_pack(git_packbuilder *pb,
|
||||
error = cb(entry_oid.id, GIT_OID_RAWSZ, data);
|
||||
|
||||
done:
|
||||
/* if callback cancelled writing, we must still free delta_data */
|
||||
for ( ; i < pb->nr_objects; ++i) {
|
||||
po = write_order[i];
|
||||
if (po->delta_data) {
|
||||
git__free(po->delta_data);
|
||||
po->delta_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
git__free(write_order);
|
||||
git_buf_free(&buf);
|
||||
return error;
|
||||
@ -1284,21 +1304,22 @@ const git_oid *git_packbuilder_hash(git_packbuilder *pb)
|
||||
return &pb->pack_oid;
|
||||
}
|
||||
|
||||
static int cb_tree_walk(const char *root, const git_tree_entry *entry, void *payload)
|
||||
static int cb_tree_walk(
|
||||
const char *root, const git_tree_entry *entry, void *payload)
|
||||
{
|
||||
int error;
|
||||
struct tree_walk_context *ctx = payload;
|
||||
|
||||
/* A commit inside a tree represents a submodule commit and should be skipped. */
|
||||
if (git_tree_entry_type(entry) == GIT_OBJ_COMMIT)
|
||||
return 0;
|
||||
|
||||
if (git_buf_sets(&ctx->buf, root) < 0 ||
|
||||
git_buf_puts(&ctx->buf, git_tree_entry_name(entry)) < 0)
|
||||
return -1;
|
||||
if (!(error = git_buf_sets(&ctx->buf, root)) &&
|
||||
!(error = git_buf_puts(&ctx->buf, git_tree_entry_name(entry))))
|
||||
error = git_packbuilder_insert(
|
||||
ctx->pb, git_tree_entry_id(entry), git_buf_cstr(&ctx->buf));
|
||||
|
||||
return git_packbuilder_insert(ctx->pb,
|
||||
git_tree_entry_id(entry),
|
||||
git_buf_cstr(&ctx->buf));
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *oid)
|
||||
@ -1318,22 +1339,17 @@ int git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *oid)
|
||||
|
||||
int git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *oid)
|
||||
{
|
||||
git_tree *tree;
|
||||
int error;
|
||||
git_tree *tree = NULL;
|
||||
struct tree_walk_context context = { pb, GIT_BUF_INIT };
|
||||
|
||||
if (git_tree_lookup(&tree, pb->repo, oid) < 0 ||
|
||||
git_packbuilder_insert(pb, oid, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
if (git_tree_walk(tree, GIT_TREEWALK_PRE, cb_tree_walk, &context) < 0) {
|
||||
git_tree_free(tree);
|
||||
git_buf_free(&context.buf);
|
||||
return -1;
|
||||
}
|
||||
if (!(error = git_tree_lookup(&tree, pb->repo, oid)) &&
|
||||
!(error = git_packbuilder_insert(pb, oid, NULL)))
|
||||
error = git_tree_walk(tree, GIT_TREEWALK_PRE, cb_tree_walk, &context);
|
||||
|
||||
git_tree_free(tree);
|
||||
git_buf_free(&context.buf);
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t git_packbuilder_object_count(git_packbuilder *pb)
|
||||
|
||||
13
src/pack.c
13
src/pack.c
@ -1042,10 +1042,9 @@ int git_pack_foreach_entry(
|
||||
{
|
||||
const unsigned char *index = p->index_map.data, *current;
|
||||
uint32_t i;
|
||||
int error = 0;
|
||||
|
||||
if (index == NULL) {
|
||||
int error;
|
||||
|
||||
if ((error = pack_index_open(p)) < 0)
|
||||
return error;
|
||||
|
||||
@ -1062,7 +1061,6 @@ int git_pack_foreach_entry(
|
||||
|
||||
if (p->oids == NULL) {
|
||||
git_vector offsets, oids;
|
||||
int error;
|
||||
|
||||
if ((error = git_vector_init(&oids, p->num_objects, NULL)))
|
||||
return error;
|
||||
@ -1084,15 +1082,16 @@ int git_pack_foreach_entry(
|
||||
git_vector_foreach(&offsets, i, current)
|
||||
git_vector_insert(&oids, (void*)¤t[4]);
|
||||
}
|
||||
|
||||
git_vector_free(&offsets);
|
||||
p->oids = (git_oid **)oids.contents;
|
||||
p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids);
|
||||
}
|
||||
|
||||
for (i = 0; i < p->num_objects; i++)
|
||||
if (cb(p->oids[i], data))
|
||||
return GIT_EUSER;
|
||||
if ((error = cb(p->oids[i], data)) != 0)
|
||||
return giterr_set_after_callback(error);
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int pack_entry_find_offset(
|
||||
|
||||
18
src/path.c
18
src/path.c
@ -436,8 +436,12 @@ int git_path_walk_up(
|
||||
while (scan >= stop) {
|
||||
error = cb(data, &iter);
|
||||
iter.ptr[scan] = oldc;
|
||||
if (error < 0)
|
||||
|
||||
if (error) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
|
||||
scan = git_buf_rfind_next(&iter, '/');
|
||||
if (scan >= 0) {
|
||||
scan++;
|
||||
@ -528,7 +532,9 @@ bool git_path_is_empty_dir(const char *path)
|
||||
if (!git_path_isdir(path))
|
||||
return false;
|
||||
|
||||
if (!(error = git_buf_sets(&dir, path)))
|
||||
if ((error = git_buf_sets(&dir, path)) != 0)
|
||||
giterr_clear();
|
||||
else
|
||||
error = git_path_direach(&dir, 0, path_found_entry, NULL);
|
||||
|
||||
git_buf_free(&dir);
|
||||
@ -778,7 +784,7 @@ int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen)
|
||||
return 0;
|
||||
|
||||
while (1) {
|
||||
if (git_buf_grow(&ic->buf, wantlen) < 0)
|
||||
if (git_buf_grow(&ic->buf, wantlen + 1) < 0)
|
||||
return -1;
|
||||
|
||||
nfc = ic->buf.ptr + ic->buf.size;
|
||||
@ -867,7 +873,7 @@ int git_path_direach(
|
||||
if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0)
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
if ((error = git_buf_put(path, de_path, de_len)) < 0)
|
||||
break;
|
||||
|
||||
@ -875,8 +881,8 @@ int git_path_direach(
|
||||
|
||||
git_buf_truncate(path, wd_len); /* restore path */
|
||||
|
||||
if (error) {
|
||||
error = GIT_EUSER;
|
||||
if (error != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,9 +255,10 @@ enum {
|
||||
* @param flags Combination of GIT_PATH_DIR flags.
|
||||
* @param callback Callback for each entry. Passed the `payload` and each
|
||||
* successive path inside the directory as a full path. This may
|
||||
* safely append text to the pathbuf if needed.
|
||||
* safely append text to the pathbuf if needed. Return non-zero to
|
||||
* cancel iteration (and return value will be propagated back).
|
||||
* @param payload Passed to callback as first argument.
|
||||
* @return 0 on success, GIT_EUSER on non-zero callback, or error code
|
||||
* @return 0 on success or error code from OS error or from callback
|
||||
*/
|
||||
extern int git_path_direach(
|
||||
git_buf *pathbuf,
|
||||
@ -288,7 +289,7 @@ extern int git_path_cmp(
|
||||
* original input path.
|
||||
* @param callback Function to invoke on each path. Passed the `payload`
|
||||
* and the buffer containing the current path. The path should not
|
||||
* be modified in any way.
|
||||
* be modified in any way. Return non-zero to stop iteration.
|
||||
* @param state Passed to fn as the first ath.
|
||||
*/
|
||||
extern int git_path_walk_up(
|
||||
|
||||
@ -102,15 +102,7 @@ int git_pathspec__vinit(
|
||||
/* free data from the pathspec vector */
|
||||
void git_pathspec__vfree(git_vector *vspec)
|
||||
{
|
||||
git_attr_fnmatch *match;
|
||||
unsigned int i;
|
||||
|
||||
git_vector_foreach(vspec, i, match) {
|
||||
git__free(match);
|
||||
vspec->contents[i] = NULL;
|
||||
}
|
||||
|
||||
git_vector_free(vspec);
|
||||
git_vector_free_deep(vspec);
|
||||
}
|
||||
|
||||
struct pathspec_match_context {
|
||||
|
||||
@ -190,19 +190,18 @@ void *git_pool_malloc(git_pool *pool, uint32_t items)
|
||||
|
||||
char *git_pool_strndup(git_pool *pool, const char *str, size_t n)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
char *ptr = NULL;
|
||||
|
||||
assert(pool && str && pool->item_size == sizeof(char));
|
||||
|
||||
if (n + 1 == 0) {
|
||||
giterr_set_oom();
|
||||
if ((uint32_t)(n + 1) < n)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ptr = git_pool_malloc(pool, (uint32_t)(n + 1))) != NULL) {
|
||||
memcpy(ptr, str, n);
|
||||
*(((char *)ptr) + n) = '\0';
|
||||
ptr[n] = '\0';
|
||||
}
|
||||
|
||||
pool->has_string_alloc = 1;
|
||||
|
||||
return ptr;
|
||||
|
||||
36
src/posix.c
36
src/posix.c
@ -203,4 +203,40 @@ int p_write(git_file fd, const void *buf, size_t cnt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef NO_MMAP
|
||||
|
||||
#include "map.h"
|
||||
|
||||
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
|
||||
{
|
||||
GIT_MMAP_VALIDATE(out, len, prot, flags);
|
||||
|
||||
out->data = NULL;
|
||||
out->len = 0;
|
||||
|
||||
if ((prot & GIT_PROT_WRITE) && ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)) {
|
||||
giterr_set(GITERR_OS, "Trying to map shared-writeable");
|
||||
return -1;
|
||||
}
|
||||
|
||||
out->data = malloc(len);
|
||||
GITERR_CHECK_ALLOC(out->data);
|
||||
|
||||
if ((p_lseek(fd, offset, SEEK_SET) < 0) || ((size_t)p_read(fd, out->data, len) != len)) {
|
||||
giterr_set(GITERR_OS, "mmap emulation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
out->len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int p_munmap(git_map *map)
|
||||
{
|
||||
assert(map != NULL);
|
||||
free(map->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
10
src/push.c
10
src/push.c
@ -541,10 +541,7 @@ static int queue_objects(git_push *push)
|
||||
error = 0;
|
||||
|
||||
on_error:
|
||||
git_vector_foreach(&commits, i, oid)
|
||||
git__free(oid);
|
||||
|
||||
git_vector_free(&commits);
|
||||
git_vector_free_deep(&commits);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -662,8 +659,9 @@ int git_push_status_foreach(git_push *push,
|
||||
unsigned int i;
|
||||
|
||||
git_vector_foreach(&push->status, i, status) {
|
||||
if (cb(status->ref, status->msg, data) < 0)
|
||||
return GIT_EUSER;
|
||||
int error = cb(status->ref, status->msg, data);
|
||||
if (error)
|
||||
return giterr_set_after_callback(error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -264,9 +264,9 @@ done:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int _dirent_loose_load(void *data, git_buf *full_path)
|
||||
static int _dirent_loose_load(void *payload, git_buf *full_path)
|
||||
{
|
||||
refdb_fs_backend *backend = (refdb_fs_backend *)data;
|
||||
refdb_fs_backend *backend = payload;
|
||||
const char *file_path;
|
||||
|
||||
if (git__suffixcmp(full_path->ptr, ".lock") == 0)
|
||||
@ -305,7 +305,7 @@ static int packed_loadloose(refdb_fs_backend *backend)
|
||||
|
||||
git_buf_free(&refs_path);
|
||||
|
||||
return (error == GIT_EUSER) ? -1 : error;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int refdb_fs_backend__exists(
|
||||
|
||||
49
src/refs.c
49
src/refs.c
@ -471,7 +471,7 @@ int git_reference_rename(
|
||||
if ((error = git_refdb_rename(out, ref->db, ref->name, new_name, force)) < 0)
|
||||
return error;
|
||||
|
||||
/* Update HEAD it was poiting to the reference being renamed. */
|
||||
/* Update HEAD it was pointing to the reference being renamed */
|
||||
if (should_head_be_updated &&
|
||||
(error = git_repository_set_head(ref->db->repo, new_name)) < 0) {
|
||||
giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
|
||||
@ -513,20 +513,19 @@ int git_reference_foreach(
|
||||
git_reference *ref;
|
||||
int error;
|
||||
|
||||
if (git_reference_iterator_new(&iter, repo) < 0)
|
||||
return -1;
|
||||
if ((error = git_reference_iterator_new(&iter, repo)) < 0)
|
||||
return error;
|
||||
|
||||
while ((error = git_reference_next(&ref, iter)) == 0) {
|
||||
if (callback(ref, payload)) {
|
||||
error = GIT_EUSER;
|
||||
goto out;
|
||||
while (!(error = git_reference_next(&ref, iter))) {
|
||||
if ((error = callback(ref, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error == GIT_ITEROVER)
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
git_reference_iterator_free(iter);
|
||||
return error;
|
||||
}
|
||||
@ -540,20 +539,19 @@ int git_reference_foreach_name(
|
||||
const char *refname;
|
||||
int error;
|
||||
|
||||
if (git_reference_iterator_new(&iter, repo) < 0)
|
||||
return -1;
|
||||
if ((error = git_reference_iterator_new(&iter, repo)) < 0)
|
||||
return error;
|
||||
|
||||
while ((error = git_reference_next_name(&refname, iter)) == 0) {
|
||||
if (callback(refname, payload)) {
|
||||
error = GIT_EUSER;
|
||||
goto out;
|
||||
while (!(error = git_reference_next_name(&refname, iter))) {
|
||||
if ((error = callback(refname, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error == GIT_ITEROVER)
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
git_reference_iterator_free(iter);
|
||||
return error;
|
||||
}
|
||||
@ -568,20 +566,19 @@ int git_reference_foreach_glob(
|
||||
const char *refname;
|
||||
int error;
|
||||
|
||||
if (git_reference_iterator_glob_new(&iter, repo, glob) < 0)
|
||||
return -1;
|
||||
if ((error = git_reference_iterator_glob_new(&iter, repo, glob)) < 0)
|
||||
return error;
|
||||
|
||||
while ((error = git_reference_next_name(&refname, iter)) == 0) {
|
||||
if (callback(refname, payload)) {
|
||||
error = GIT_EUSER;
|
||||
goto out;
|
||||
while (!(error = git_reference_next_name(&refname, iter))) {
|
||||
if ((error = callback(refname, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error == GIT_ITEROVER)
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
git_reference_iterator_free(iter);
|
||||
return error;
|
||||
}
|
||||
@ -624,7 +621,9 @@ void git_reference_iterator_free(git_reference_iterator *iter)
|
||||
|
||||
static int cb__reflist_add(const char *ref, void *data)
|
||||
{
|
||||
return git_vector_insert((git_vector *)data, git__strdup(ref));
|
||||
char *name = git__strdup(ref);
|
||||
GITERR_CHECK_ALLOC(name);
|
||||
return git_vector_insert((git_vector *)data, name);
|
||||
}
|
||||
|
||||
int git_reference_list(
|
||||
@ -647,8 +646,8 @@ int git_reference_list(
|
||||
return -1;
|
||||
}
|
||||
|
||||
array->strings = (char **)ref_list.contents;
|
||||
array->count = ref_list.length;
|
||||
array->strings = (char **)git_vector_detach(&array->count, NULL, &ref_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
238
src/remote.c
238
src/remote.c
@ -45,7 +45,7 @@ static int add_refspec(git_remote *remote, const char *string, bool is_fetch)
|
||||
|
||||
static int download_tags_value(git_remote *remote, git_config *cfg)
|
||||
{
|
||||
const char *val;
|
||||
const git_config_entry *ce;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
int error;
|
||||
|
||||
@ -53,16 +53,14 @@ static int download_tags_value(git_remote *remote, git_config *cfg)
|
||||
if (git_buf_printf(&buf, "remote.%s.tagopt", remote->name) < 0)
|
||||
return -1;
|
||||
|
||||
error = git_config_get_string(&val, cfg, git_buf_cstr(&buf));
|
||||
error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
|
||||
git_buf_free(&buf);
|
||||
if (!error && !strcmp(val, "--no-tags"))
|
||||
remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
|
||||
else if (!error && !strcmp(val, "--tags"))
|
||||
remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
|
||||
|
||||
if (error == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
if (!error && ce && ce->value) {
|
||||
if (!strcmp(ce->value, "--no-tags"))
|
||||
remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_NONE;
|
||||
else if (!strcmp(ce->value, "--tags"))
|
||||
remote->download_tags = GIT_REMOTE_DOWNLOAD_TAGS_ALL;
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -104,12 +102,7 @@ static int get_check_cert(int *out, git_repository *repo)
|
||||
if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
|
||||
return error;
|
||||
|
||||
if ((error = git_config_get_bool(out, cfg, "http.sslVerify")) == 0)
|
||||
return 0;
|
||||
else if (error != GIT_ENOTFOUND)
|
||||
return error;
|
||||
|
||||
giterr_clear();
|
||||
*out = git_config__get_bool_force(cfg, "http.sslverify", 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -262,8 +255,7 @@ struct refspec_cb_data {
|
||||
|
||||
static int refspec_cb(const git_config_entry *entry, void *payload)
|
||||
{
|
||||
const struct refspec_cb_data *data = (struct refspec_cb_data *)payload;
|
||||
|
||||
struct refspec_cb_data *data = (struct refspec_cb_data *)payload;
|
||||
return add_refspec(data->remote, entry->value, data->fetch);
|
||||
}
|
||||
|
||||
@ -290,9 +282,6 @@ static int get_optional_config(
|
||||
error = 0;
|
||||
}
|
||||
|
||||
if (error < 0)
|
||||
error = -1;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -303,7 +292,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
|
||||
const char *val;
|
||||
int error = 0;
|
||||
git_config *config;
|
||||
struct refspec_cb_data data;
|
||||
struct refspec_cb_data data = { NULL };
|
||||
bool optional_setting_found = false, found;
|
||||
|
||||
assert(out && repo && name);
|
||||
@ -325,17 +314,15 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
|
||||
if ((error = get_check_cert(&remote->check_cert, repo)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if ((git_vector_init(&remote->refs, 32, NULL) < 0) ||
|
||||
(git_vector_init(&remote->refspecs, 2, NULL) < 0) ||
|
||||
(git_vector_init(&remote->active_refspecs, 2, NULL) < 0)) {
|
||||
if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
|
||||
git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
|
||||
git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
|
||||
error = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (git_buf_printf(&buf, "remote.%s.url", name) < 0) {
|
||||
error = -1;
|
||||
if ((error = git_buf_printf(&buf, "remote.%s.url", name)) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0)
|
||||
goto cleanup;
|
||||
@ -370,6 +357,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
|
||||
|
||||
data.remote = remote;
|
||||
data.fetch = true;
|
||||
|
||||
git_buf_clear(&buf);
|
||||
git_buf_printf(&buf, "remote.%s.fetch", name);
|
||||
|
||||
@ -493,7 +481,7 @@ int git_remote_save(const git_remote *remote)
|
||||
}
|
||||
if (error < 0) {
|
||||
git_buf_free(&buf);
|
||||
return -1;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -641,7 +629,7 @@ int git_remote_connect(git_remote *remote, git_direction direction)
|
||||
if (!remote->check_cert)
|
||||
flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT;
|
||||
|
||||
if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) < 0)
|
||||
if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) != 0)
|
||||
goto on_error;
|
||||
|
||||
remote->transport = t;
|
||||
@ -667,7 +655,8 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote
|
||||
int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
|
||||
{
|
||||
git_config *cfg;
|
||||
const char *val;
|
||||
const git_config_entry *ce;
|
||||
const char *val = NULL;
|
||||
int error;
|
||||
|
||||
assert(remote);
|
||||
@ -684,44 +673,39 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur
|
||||
* to least specific. */
|
||||
|
||||
/* remote.<name>.proxy config setting */
|
||||
if (remote->name && 0 != *(remote->name)) {
|
||||
if (remote->name && remote->name[0]) {
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0)
|
||||
return error;
|
||||
|
||||
if ((error = git_config_get_string(&val, cfg, git_buf_cstr(&buf))) == 0 &&
|
||||
val && ('\0' != *val)) {
|
||||
git_buf_free(&buf);
|
||||
error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
|
||||
git_buf_free(&buf);
|
||||
|
||||
*proxy_url = git__strdup(val);
|
||||
GITERR_CHECK_ALLOC(*proxy_url);
|
||||
return 0;
|
||||
} else if (error != GIT_ENOTFOUND)
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
giterr_clear();
|
||||
git_buf_free(&buf);
|
||||
if (ce && ce->value) {
|
||||
val = ce->value;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
/* http.proxy config setting */
|
||||
if ((error = git_config_get_string(&val, cfg, "http.proxy")) == 0 &&
|
||||
val && ('\0' != *val)) {
|
||||
*proxy_url = git__strdup(val);
|
||||
GITERR_CHECK_ALLOC(*proxy_url);
|
||||
return 0;
|
||||
} else if (error != GIT_ENOTFOUND)
|
||||
if ((error = git_config__lookup_entry(&ce, cfg, "http.proxy", false)) < 0)
|
||||
return error;
|
||||
|
||||
giterr_clear();
|
||||
if (ce && ce->value) {
|
||||
val = ce->value;
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* HTTP_PROXY / HTTPS_PROXY environment variables */
|
||||
val = use_ssl ? getenv("HTTPS_PROXY") : getenv("HTTP_PROXY");
|
||||
|
||||
if (val && ('\0' != *val)) {
|
||||
found:
|
||||
if (val && val[0]) {
|
||||
*proxy_url = git__strdup(val);
|
||||
GITERR_CHECK_ALLOC(*proxy_url);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -797,7 +781,7 @@ int git_remote_download(git_remote *remote)
|
||||
git_vector_free(&refs);
|
||||
|
||||
if (error < 0)
|
||||
return -1;
|
||||
return error;
|
||||
|
||||
if ((error = git_fetch_negotiate(remote)) < 0)
|
||||
return error;
|
||||
@ -810,10 +794,10 @@ int git_remote_fetch(git_remote *remote)
|
||||
int error;
|
||||
|
||||
/* Connect and download everything */
|
||||
if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) < 0)
|
||||
if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) != 0)
|
||||
return error;
|
||||
|
||||
if ((error = git_remote_download(remote)) < 0)
|
||||
if ((error = git_remote_download(remote)) != 0)
|
||||
return error;
|
||||
|
||||
/* We don't need to be connected anymore */
|
||||
@ -1041,7 +1025,6 @@ int git_remote_update_tips(git_remote *remote)
|
||||
int error;
|
||||
size_t i;
|
||||
|
||||
|
||||
if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
|
||||
return -1;
|
||||
|
||||
@ -1141,40 +1124,28 @@ static int remote_list_cb(const git_config_entry *entry, void *payload)
|
||||
|
||||
int git_remote_list(git_strarray *remotes_list, git_repository *repo)
|
||||
{
|
||||
git_config *cfg;
|
||||
git_vector list;
|
||||
int error;
|
||||
git_config *cfg;
|
||||
git_vector list = GIT_VECTOR_INIT;
|
||||
|
||||
if (git_repository_config__weakptr(&cfg, repo) < 0)
|
||||
return -1;
|
||||
if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
|
||||
return error;
|
||||
|
||||
if (git_vector_init(&list, 4, git__strcmp_cb) < 0)
|
||||
return -1;
|
||||
if ((error = git_vector_init(&list, 4, git__strcmp_cb)) < 0)
|
||||
return error;
|
||||
|
||||
error = git_config_foreach_match(
|
||||
cfg, "^remote\\..*\\.(push)?url$", remote_list_cb, &list);
|
||||
|
||||
if (error < 0) {
|
||||
size_t i;
|
||||
char *elem;
|
||||
|
||||
git_vector_foreach(&list, i, elem) {
|
||||
git__free(elem);
|
||||
}
|
||||
|
||||
git_vector_free(&list);
|
||||
|
||||
/* cb error is converted to GIT_EUSER by git_config_foreach */
|
||||
if (error == GIT_EUSER)
|
||||
error = -1;
|
||||
|
||||
git_vector_free_deep(&list);
|
||||
return error;
|
||||
}
|
||||
|
||||
git_vector_uniq(&list, git__free);
|
||||
|
||||
remotes_list->strings = (char **)list.contents;
|
||||
remotes_list->count = list.length;
|
||||
remotes_list->strings =
|
||||
(char **)git_vector_detach(&remotes_list->count, NULL, &list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1261,8 +1232,7 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
struct update_data
|
||||
{
|
||||
struct update_data {
|
||||
git_config *config;
|
||||
const char *old_remote_name;
|
||||
const char *new_remote_name;
|
||||
@ -1278,9 +1248,7 @@ static int update_config_entries_cb(
|
||||
return 0;
|
||||
|
||||
return git_config_set_string(
|
||||
data->config,
|
||||
entry->name,
|
||||
data->new_remote_name);
|
||||
data->config, entry->name, data->new_remote_name);
|
||||
}
|
||||
|
||||
static int update_branch_remote_config_entry(
|
||||
@ -1288,20 +1256,17 @@ static int update_branch_remote_config_entry(
|
||||
const char *old_name,
|
||||
const char *new_name)
|
||||
{
|
||||
git_config *config;
|
||||
struct update_data data;
|
||||
int error;
|
||||
struct update_data data = { NULL };
|
||||
|
||||
if (git_repository_config__weakptr(&config, repo) < 0)
|
||||
return -1;
|
||||
if ((error = git_repository_config__weakptr(&data.config, repo)) < 0)
|
||||
return error;
|
||||
|
||||
data.config = config;
|
||||
data.old_remote_name = old_name;
|
||||
data.new_remote_name = new_name;
|
||||
|
||||
return git_config_foreach_match(
|
||||
config,
|
||||
"branch\\..+\\.remote",
|
||||
update_config_entries_cb, &data);
|
||||
data.config, "branch\\..+\\.remote", update_config_entries_cb, &data);
|
||||
}
|
||||
|
||||
static int rename_one_remote_reference(
|
||||
@ -1309,18 +1274,20 @@ static int rename_one_remote_reference(
|
||||
const char *old_remote_name,
|
||||
const char *new_remote_name)
|
||||
{
|
||||
int error = -1;
|
||||
int error;
|
||||
git_buf new_name = GIT_BUF_INIT;
|
||||
|
||||
if (git_buf_printf(
|
||||
error = git_buf_printf(
|
||||
&new_name,
|
||||
GIT_REFS_REMOTES_DIR "%s%s",
|
||||
new_remote_name,
|
||||
reference->name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name)) < 0)
|
||||
return -1;
|
||||
reference->name + strlen(GIT_REFS_REMOTES_DIR) + strlen(old_remote_name));
|
||||
|
||||
error = git_reference_rename(NULL, reference, git_buf_cstr(&new_name), 0);
|
||||
git_reference_free(reference);
|
||||
if (!error) {
|
||||
error = git_reference_rename(
|
||||
NULL, reference, git_buf_cstr(&new_name), 0);
|
||||
git_reference_free(reference);
|
||||
}
|
||||
|
||||
git_buf_free(&new_name);
|
||||
return error;
|
||||
@ -1331,12 +1298,12 @@ static int rename_remote_references(
|
||||
const char *old_name,
|
||||
const char *new_name)
|
||||
{
|
||||
int error = -1;
|
||||
int error;
|
||||
git_reference *ref;
|
||||
git_reference_iterator *iter;
|
||||
|
||||
if (git_reference_iterator_new(&iter, repo) < 0)
|
||||
return -1;
|
||||
if ((error = git_reference_iterator_new(&iter, repo)) < 0)
|
||||
return error;
|
||||
|
||||
while ((error = git_reference_next(&ref, iter)) == 0) {
|
||||
if (git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR)) {
|
||||
@ -1344,18 +1311,13 @@ static int rename_remote_references(
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((error = rename_one_remote_reference(ref, old_name, new_name)) < 0) {
|
||||
git_reference_iterator_free(iter);
|
||||
return error;
|
||||
}
|
||||
if ((error = rename_one_remote_reference(ref, old_name, new_name)) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
git_reference_iterator_free(iter);
|
||||
|
||||
if (error == GIT_ITEROVER)
|
||||
return 0;
|
||||
|
||||
return error;
|
||||
return (error == GIT_ITEROVER) ? 0 : error;
|
||||
}
|
||||
|
||||
static int rename_fetch_refspecs(
|
||||
@ -1368,52 +1330,50 @@ static int rename_fetch_refspecs(
|
||||
git_buf base = GIT_BUF_INIT, var = GIT_BUF_INIT, val = GIT_BUF_INIT;
|
||||
const git_refspec *spec;
|
||||
size_t i;
|
||||
int error = -1;
|
||||
int error = 0;
|
||||
|
||||
if (git_buf_printf(&base, "+refs/heads/*:refs/remotes/%s/*", remote->name) < 0)
|
||||
goto cleanup;
|
||||
if ((error = git_repository_config__weakptr(&config, remote->repo)) < 0)
|
||||
return error;
|
||||
|
||||
if ((error = git_buf_printf(
|
||||
&base, "+refs/heads/*:refs/remotes/%s/*", remote->name)) < 0)
|
||||
return error;
|
||||
|
||||
git_vector_foreach(&remote->refspecs, i, spec) {
|
||||
if (spec->push)
|
||||
continue;
|
||||
|
||||
/* Every refspec is a problem refspec for an in-memory remote */
|
||||
if (!remote->name) {
|
||||
if (callback(spec->string, payload) < 0) {
|
||||
error = GIT_EUSER;
|
||||
goto cleanup;
|
||||
}
|
||||
/* Every refspec is a problem refspec for an in-memory remote, OR */
|
||||
/* Does the dst part of the refspec follow the expected format? */
|
||||
if (!remote->name ||
|
||||
strcmp(git_buf_cstr(&base), spec->string)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Does the dst part of the refspec follow the extected standard format? */
|
||||
if (strcmp(git_buf_cstr(&base), spec->string)) {
|
||||
if (callback(spec->string, payload) < 0) {
|
||||
error = GIT_EUSER;
|
||||
goto cleanup;
|
||||
if ((error = callback(spec->string, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we do want to move it to the new section */
|
||||
if (git_buf_printf(&val, "+refs/heads/*:refs/remotes/%s/*", new_name) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
|
||||
goto cleanup;
|
||||
git_buf_clear(&val);
|
||||
git_buf_clear(&var);
|
||||
|
||||
if (git_repository_config__weakptr(&config, remote->repo) < 0)
|
||||
goto cleanup;
|
||||
if (git_buf_printf(
|
||||
&val, "+refs/heads/*:refs/remotes/%s/*", new_name) < 0 ||
|
||||
git_buf_printf(&var, "remote.%s.fetch", new_name) < 0)
|
||||
{
|
||||
error = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (git_config_set_string(config, git_buf_cstr(&var), git_buf_cstr(&val)) < 0)
|
||||
goto cleanup;
|
||||
if ((error = git_config_set_string(
|
||||
config, git_buf_cstr(&var), git_buf_cstr(&val))) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&base);
|
||||
git_buf_free(&var);
|
||||
git_buf_free(&val);
|
||||
@ -1448,11 +1408,11 @@ int git_remote_rename(
|
||||
new_name,
|
||||
callback,
|
||||
payload)) < 0)
|
||||
return error;
|
||||
return error;
|
||||
|
||||
remote->name = git__strdup(new_name);
|
||||
GITERR_CHECK_ALLOC(remote->name);
|
||||
|
||||
if (!remote->name) return 0;
|
||||
return git_remote_save(remote);
|
||||
}
|
||||
|
||||
@ -1479,11 +1439,13 @@ int git_remote_rename(
|
||||
new_name,
|
||||
callback,
|
||||
payload)) < 0)
|
||||
return error;
|
||||
return error;
|
||||
}
|
||||
|
||||
git__free(remote->name);
|
||||
|
||||
remote->name = git__strdup(new_name);
|
||||
GITERR_CHECK_ALLOC(remote->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1655,9 +1617,7 @@ static int copy_refspecs(git_strarray *array, git_remote *remote, unsigned int p
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
git_vector_foreach(&refspecs, i, dup)
|
||||
git__free(dup);
|
||||
git_vector_free(&refspecs);
|
||||
git_vector_free_deep(&refspecs);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -186,39 +186,37 @@ static int load_workdir(git_repository *repo, git_buf *parent_path)
|
||||
{
|
||||
int error;
|
||||
git_config *config;
|
||||
const char *worktree;
|
||||
git_buf worktree_buf = GIT_BUF_INIT;
|
||||
const git_config_entry *ce;
|
||||
git_buf worktree = GIT_BUF_INIT;
|
||||
|
||||
if (repo->is_bare)
|
||||
return 0;
|
||||
|
||||
if (git_repository_config__weakptr(&config, repo) < 0)
|
||||
return -1;
|
||||
|
||||
error = git_config_get_string(&worktree, config, "core.worktree");
|
||||
if (!error && worktree != NULL) {
|
||||
error = git_path_prettify_dir(
|
||||
&worktree_buf, worktree, repo->path_repository);
|
||||
if (error < 0)
|
||||
return error;
|
||||
repo->workdir = git_buf_detach(&worktree_buf);
|
||||
}
|
||||
else if (error != GIT_ENOTFOUND)
|
||||
if ((error = git_repository_config__weakptr(&config, repo)) < 0)
|
||||
return error;
|
||||
else {
|
||||
giterr_clear();
|
||||
|
||||
if (parent_path && git_path_isdir(parent_path->ptr))
|
||||
repo->workdir = git_buf_detach(parent_path);
|
||||
else {
|
||||
git_path_dirname_r(&worktree_buf, repo->path_repository);
|
||||
git_path_to_dir(&worktree_buf);
|
||||
repo->workdir = git_buf_detach(&worktree_buf);
|
||||
}
|
||||
if ((error = git_config__lookup_entry(
|
||||
&ce, config, "core.worktree", false)) < 0)
|
||||
return error;
|
||||
|
||||
if (ce && ce->value) {
|
||||
if ((error = git_path_prettify_dir(
|
||||
&worktree, ce->value, repo->path_repository)) < 0)
|
||||
return error;
|
||||
|
||||
repo->workdir = git_buf_detach(&worktree);
|
||||
}
|
||||
else if (parent_path && git_path_isdir(parent_path->ptr))
|
||||
repo->workdir = git_buf_detach(parent_path);
|
||||
else {
|
||||
if (git_path_dirname_r(&worktree, repo->path_repository) < 0 ||
|
||||
git_path_to_dir(&worktree) < 0)
|
||||
return -1;
|
||||
|
||||
repo->workdir = git_buf_detach(&worktree);
|
||||
}
|
||||
|
||||
GITERR_CHECK_ALLOC(repo->workdir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1610,15 +1608,14 @@ static int at_least_one_cb(const char *refname, void *payload)
|
||||
{
|
||||
GIT_UNUSED(refname);
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
return GIT_EUSER;
|
||||
return GIT_PASSTHROUGH;
|
||||
}
|
||||
|
||||
static int repo_contains_no_reference(git_repository *repo)
|
||||
{
|
||||
int error = git_reference_foreach_name(repo, &at_least_one_cb, NULL);
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
if (error == GIT_PASSTHROUGH)
|
||||
return 0;
|
||||
|
||||
if (!error)
|
||||
|
||||
@ -112,12 +112,13 @@ static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commi
|
||||
|
||||
static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
|
||||
{
|
||||
int error;
|
||||
git_object *obj;
|
||||
git_otype type;
|
||||
git_commit_list_node *commit;
|
||||
|
||||
if (git_object_lookup(&obj, walk->repo, oid, GIT_OBJ_ANY) < 0)
|
||||
return -1;
|
||||
if ((error = git_object_lookup(&obj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
|
||||
return error;
|
||||
|
||||
type = git_object_type(obj);
|
||||
git_object_free(obj);
|
||||
@ -173,7 +174,6 @@ struct push_cb_data {
|
||||
static int push_glob_cb(const char *refname, void *data_)
|
||||
{
|
||||
struct push_cb_data *data = (struct push_cb_data *)data_;
|
||||
|
||||
return push_ref(data->walk, refname, data->hide);
|
||||
}
|
||||
|
||||
@ -191,6 +191,8 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
|
||||
git_buf_joinpath(&buf, GIT_REFS_DIR, glob);
|
||||
else
|
||||
git_buf_puts(&buf, glob);
|
||||
if (git_buf_oom(&buf))
|
||||
return -1;
|
||||
|
||||
/* If no '?', '*' or '[' exist, we append '/ *' to the glob */
|
||||
wildcard = strcspn(glob, "?*[");
|
||||
@ -200,11 +202,8 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
|
||||
data.walk = walk;
|
||||
data.hide = hide;
|
||||
|
||||
if (git_buf_oom(&buf))
|
||||
error = -1;
|
||||
else
|
||||
error = git_reference_foreach_glob(
|
||||
walk->repo, git_buf_cstr(&buf), push_glob_cb, &data);
|
||||
error = git_reference_foreach_glob(
|
||||
walk->repo, git_buf_cstr(&buf), push_glob_cb, &data);
|
||||
|
||||
git_buf_free(&buf);
|
||||
return error;
|
||||
|
||||
14
src/stash.c
14
src/stash.c
@ -440,7 +440,7 @@ static int is_dirty_cb(const char *path, unsigned int status, void *payload)
|
||||
GIT_UNUSED(status);
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
return 1;
|
||||
return GIT_PASSTHROUGH;
|
||||
}
|
||||
|
||||
static int ensure_there_are_changes_to_stash(
|
||||
@ -463,7 +463,7 @@ static int ensure_there_are_changes_to_stash(
|
||||
|
||||
error = git_status_foreach_ext(repo, &opts, is_dirty_cb, NULL);
|
||||
|
||||
if (error == GIT_EUSER)
|
||||
if (error == GIT_PASSTHROUGH)
|
||||
return 0;
|
||||
|
||||
if (!error)
|
||||
@ -582,12 +582,14 @@ int git_stash_foreach(
|
||||
for (i = 0; i < max; i++) {
|
||||
entry = git_reflog_entry_byindex(reflog, i);
|
||||
|
||||
if (callback(i,
|
||||
error = callback(i,
|
||||
git_reflog_entry_message(entry),
|
||||
git_reflog_entry_id_new(entry),
|
||||
payload)) {
|
||||
error = GIT_EUSER;
|
||||
break;
|
||||
payload);
|
||||
|
||||
if (error) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
18
src/status.c
18
src/status.c
@ -314,8 +314,9 @@ int git_status_list_new(
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((error = git_diff__paired_foreach(
|
||||
status->head2idx, status->idx2wd, status_collect, status)) < 0)
|
||||
error = git_diff__paired_foreach(
|
||||
status->head2idx, status->idx2wd, status_collect, status);
|
||||
if (error < 0)
|
||||
goto done;
|
||||
|
||||
if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY)
|
||||
@ -360,19 +361,13 @@ const git_status_entry *git_status_byindex(git_status_list *status, size_t i)
|
||||
|
||||
void git_status_list_free(git_status_list *status)
|
||||
{
|
||||
git_status_entry *status_entry;
|
||||
size_t i;
|
||||
|
||||
if (status == NULL)
|
||||
return;
|
||||
|
||||
git_diff_free(status->head2idx);
|
||||
git_diff_free(status->idx2wd);
|
||||
|
||||
git_vector_foreach(&status->paired, i, status_entry)
|
||||
git__free(status_entry);
|
||||
|
||||
git_vector_free(&status->paired);
|
||||
git_vector_free_deep(&status->paired);
|
||||
|
||||
git__memzero(status, sizeof(*status));
|
||||
git__free(status);
|
||||
@ -397,9 +392,8 @@ int git_status_foreach_ext(
|
||||
status_entry->head_to_index->old_file.path :
|
||||
status_entry->index_to_workdir->old_file.path;
|
||||
|
||||
if (cb(path, status_entry->status, payload) != 0) {
|
||||
error = GIT_EUSER;
|
||||
giterr_clear();
|
||||
if ((error = cb(path, status_entry->status, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
116
src/submodule.c
116
src/submodule.c
@ -168,9 +168,8 @@ int git_submodule_foreach(
|
||||
break;
|
||||
}
|
||||
|
||||
if (callback(sm, sm->name, payload)) {
|
||||
giterr_clear();
|
||||
error = GIT_EUSER;
|
||||
if ((error = callback(sm, sm->name, payload)) != 0) {
|
||||
giterr_set_after_callback(error);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@ -825,17 +824,14 @@ int git_submodule_reload(git_submodule *submodule)
|
||||
assert(submodule);
|
||||
|
||||
/* refresh index data */
|
||||
|
||||
if (submodule_update_index(submodule) < 0)
|
||||
return -1;
|
||||
if ((error = submodule_update_index(submodule)) < 0)
|
||||
return error;
|
||||
|
||||
/* refresh HEAD tree data */
|
||||
|
||||
if (submodule_update_head(submodule) < 0)
|
||||
return -1;
|
||||
if ((error = submodule_update_head(submodule)) < 0)
|
||||
return error;
|
||||
|
||||
/* refresh config data */
|
||||
|
||||
mods = open_gitmodules(submodule->repo, false, NULL);
|
||||
if (mods != NULL) {
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
@ -852,19 +848,17 @@ int git_submodule_reload(git_submodule *submodule)
|
||||
|
||||
git_buf_free(&path);
|
||||
git_config_file_free(mods);
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
/* refresh wd data */
|
||||
|
||||
submodule->flags = submodule->flags &
|
||||
~(GIT_SUBMODULE_STATUS_IN_WD | GIT_SUBMODULE_STATUS__WD_OID_VALID);
|
||||
|
||||
error = submodule_load_from_wd_lite(submodule, submodule->path, NULL);
|
||||
|
||||
return error;
|
||||
return submodule_load_from_wd_lite(
|
||||
submodule, submodule->path, submodule->repo);
|
||||
}
|
||||
|
||||
static void submodule_copy_oid_maybe(
|
||||
@ -1087,15 +1081,14 @@ int git_submodule_parse_update(git_submodule_update_t *out, const char *value)
|
||||
}
|
||||
|
||||
static int submodule_load_from_config(
|
||||
const git_config_entry *entry, void *data)
|
||||
const git_config_entry *entry, void *payload)
|
||||
{
|
||||
git_repository *repo = data;
|
||||
git_repository *repo = payload;
|
||||
git_strmap *smcfg = repo->submodules;
|
||||
const char *namestart, *property, *alternate = NULL;
|
||||
const char *key = entry->name, *value = entry->value;
|
||||
const char *key = entry->name, *value = entry->value, *path;
|
||||
git_buf name = GIT_BUF_INIT;
|
||||
git_submodule *sm;
|
||||
bool is_path;
|
||||
int error = 0;
|
||||
|
||||
if (git__prefixcmp(key, "submodule.") != 0)
|
||||
@ -1108,15 +1101,11 @@ static int submodule_load_from_config(
|
||||
return 0;
|
||||
|
||||
property++;
|
||||
is_path = (strcasecmp(property, "path") == 0);
|
||||
path = !strcasecmp(property, "path") ? value : NULL;
|
||||
|
||||
if (git_buf_set(&name, namestart, property - namestart - 1) < 0)
|
||||
return -1;
|
||||
|
||||
if (submodule_get(&sm, repo, name.ptr, is_path ? value : NULL) < 0) {
|
||||
git_buf_free(&name);
|
||||
return -1;
|
||||
}
|
||||
if ((error = git_buf_set(&name, namestart, property - namestart - 1)) < 0 ||
|
||||
(error = submodule_get(&sm, repo, name.ptr, path)) < 0)
|
||||
goto done;
|
||||
|
||||
sm->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG;
|
||||
|
||||
@ -1130,15 +1119,20 @@ static int submodule_load_from_config(
|
||||
|
||||
if (strcmp(sm->name, name.ptr) != 0) {
|
||||
alternate = sm->name = git_buf_detach(&name);
|
||||
} else if (is_path && value && strcmp(sm->path, value) != 0) {
|
||||
} else if (path && strcmp(path, sm->path) != 0) {
|
||||
alternate = sm->path = git__strdup(value);
|
||||
if (!sm->path)
|
||||
if (!sm->path) {
|
||||
error = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (alternate) {
|
||||
void *old_sm = NULL;
|
||||
git_strmap_insert2(smcfg, alternate, sm, old_sm, error);
|
||||
|
||||
if (error < 0)
|
||||
goto done;
|
||||
if (error >= 0)
|
||||
GIT_REFCOUNT_INC(sm); /* inserted under a new key */
|
||||
|
||||
@ -1149,42 +1143,44 @@ static int submodule_load_from_config(
|
||||
}
|
||||
}
|
||||
|
||||
git_buf_free(&name);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
/* TODO: Look up path in index and if it is present but not a GITLINK
|
||||
* then this should be deleted (at least to match git's behavior)
|
||||
*/
|
||||
|
||||
if (is_path)
|
||||
return 0;
|
||||
if (path)
|
||||
goto done;
|
||||
|
||||
/* copy other properties into submodule entry */
|
||||
if (strcasecmp(property, "url") == 0) {
|
||||
git__free(sm->url);
|
||||
sm->url = NULL;
|
||||
|
||||
if (value != NULL && (sm->url = git__strdup(value)) == NULL)
|
||||
return -1;
|
||||
if (value != NULL && (sm->url = git__strdup(value)) == NULL) {
|
||||
error = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(property, "update") == 0) {
|
||||
if (git_submodule_parse_update(&sm->update, value) < 0)
|
||||
return -1;
|
||||
if ((error = git_submodule_parse_update(&sm->update, value)) < 0)
|
||||
goto done;
|
||||
sm->update_default = sm->update;
|
||||
}
|
||||
else if (strcasecmp(property, "fetchRecurseSubmodules") == 0) {
|
||||
if (git__parse_bool(&sm->fetch_recurse, value) < 0)
|
||||
return submodule_config_error("fetchRecurseSubmodules", value);
|
||||
if (git__parse_bool(&sm->fetch_recurse, value) < 0) {
|
||||
error = submodule_config_error("fetchRecurseSubmodules", value);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(property, "ignore") == 0) {
|
||||
if (git_submodule_parse_ignore(&sm->ignore, value) < 0)
|
||||
return -1;
|
||||
if ((error = git_submodule_parse_ignore(&sm->ignore, value)) < 0)
|
||||
goto done;
|
||||
sm->ignore_default = sm->ignore;
|
||||
}
|
||||
/* ignore other unknown submodule properties */
|
||||
|
||||
return 0;
|
||||
done:
|
||||
git_buf_free(&name);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int submodule_load_from_wd_lite(
|
||||
@ -1192,8 +1188,7 @@ static int submodule_load_from_wd_lite(
|
||||
{
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
GIT_UNUSED(name);
|
||||
GIT_UNUSED(payload);
|
||||
GIT_UNUSED(name); GIT_UNUSED(payload);
|
||||
|
||||
if (git_repository_is_bare(sm->repo))
|
||||
return 0;
|
||||
@ -1208,7 +1203,6 @@ static int submodule_load_from_wd_lite(
|
||||
sm->flags |= GIT_SUBMODULE_STATUS_IN_WD;
|
||||
|
||||
git_buf_free(&path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1342,7 +1336,6 @@ static int load_submodule_config(git_repository *repo)
|
||||
{
|
||||
int error;
|
||||
git_oid gitmodules_oid;
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
git_config_backend *mods = NULL;
|
||||
|
||||
if (repo->submodules)
|
||||
@ -1370,10 +1363,9 @@ static int load_submodule_config(git_repository *repo)
|
||||
|
||||
/* add submodule information from .gitmodules */
|
||||
|
||||
if ((mods = open_gitmodules(repo, false, &gitmodules_oid)) != NULL)
|
||||
error = git_config_file_foreach(mods, submodule_load_from_config, repo);
|
||||
|
||||
if (error != 0)
|
||||
if ((mods = open_gitmodules(repo, false, &gitmodules_oid)) != NULL &&
|
||||
(error = git_config_file_foreach(
|
||||
mods, submodule_load_from_config, repo)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* shallow scan submodules in work tree */
|
||||
@ -1382,8 +1374,6 @@ static int load_submodule_config(git_repository *repo)
|
||||
error = git_submodule_foreach(repo, submodule_load_from_wd_lite, NULL);
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&path);
|
||||
|
||||
if (mods != NULL)
|
||||
git_config_file_free(mods);
|
||||
|
||||
@ -1468,7 +1458,7 @@ static int submodule_update_config(
|
||||
int error;
|
||||
git_config *config;
|
||||
git_buf key = GIT_BUF_INIT;
|
||||
const char *old = NULL;
|
||||
const git_config_entry *ce = NULL;
|
||||
|
||||
assert(submodule);
|
||||
|
||||
@ -1480,14 +1470,16 @@ static int submodule_update_config(
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_config_get_string(&old, config, key.ptr) < 0)
|
||||
giterr_clear();
|
||||
if ((error = git_config__lookup_entry(&ce, config, key.ptr, false)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!old && only_existing)
|
||||
if (!ce && only_existing)
|
||||
goto cleanup;
|
||||
if (old && !overwrite)
|
||||
if (ce && !overwrite)
|
||||
goto cleanup;
|
||||
if ((!old && !value) || (old && value && strcmp(old, value) == 0))
|
||||
if (value && ce && ce->value && !strcmp(ce->value, value))
|
||||
goto cleanup;
|
||||
if (!value && (!ce || !ce->value))
|
||||
goto cleanup;
|
||||
|
||||
if (!value)
|
||||
|
||||
35
src/tag.c
35
src/tag.c
@ -418,16 +418,19 @@ typedef struct {
|
||||
|
||||
static int tags_cb(const char *ref, void *data)
|
||||
{
|
||||
int error;
|
||||
git_oid oid;
|
||||
tag_cb_data *d = (tag_cb_data *)data;
|
||||
|
||||
if (git__prefixcmp(ref, GIT_REFS_TAGS_DIR) != 0)
|
||||
return 0; /* no tag */
|
||||
|
||||
if (git_reference_name_to_id(&oid, d->repo, ref) < 0)
|
||||
return -1;
|
||||
if (!(error = git_reference_name_to_id(&oid, d->repo, ref))) {
|
||||
if ((error = d->cb(ref, &oid, d->cb_data)) != 0)
|
||||
giterr_set_after_callback_function(error, "git_tag_foreach");
|
||||
}
|
||||
|
||||
return d->cb(ref, &oid, d->cb_data);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_tag_foreach(git_repository *repo, git_tag_foreach_cb cb, void *cb_data)
|
||||
@ -455,8 +458,14 @@ static int tag_list_cb(const char *tag_name, git_oid *oid, void *data)
|
||||
tag_filter_data *filter = (tag_filter_data *)data;
|
||||
GIT_UNUSED(oid);
|
||||
|
||||
if (!*filter->pattern || p_fnmatch(filter->pattern, tag_name + GIT_REFS_TAGS_DIR_LEN, 0) == 0)
|
||||
return git_vector_insert(filter->taglist, git__strdup(tag_name + GIT_REFS_TAGS_DIR_LEN));
|
||||
if (!*filter->pattern ||
|
||||
p_fnmatch(filter->pattern, tag_name + GIT_REFS_TAGS_DIR_LEN, 0) == 0)
|
||||
{
|
||||
char *matched = git__strdup(tag_name + GIT_REFS_TAGS_DIR_LEN);
|
||||
GITERR_CHECK_ALLOC(matched);
|
||||
|
||||
return git_vector_insert(filter->taglist, matched);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -469,20 +478,20 @@ int git_tag_list_match(git_strarray *tag_names, const char *pattern, git_reposit
|
||||
|
||||
assert(tag_names && repo && pattern);
|
||||
|
||||
if (git_vector_init(&taglist, 8, NULL) < 0)
|
||||
return -1;
|
||||
if ((error = git_vector_init(&taglist, 8, NULL)) < 0)
|
||||
return error;
|
||||
|
||||
filter.taglist = &taglist;
|
||||
filter.pattern = pattern;
|
||||
|
||||
error = git_tag_foreach(repo, &tag_list_cb, (void *)&filter);
|
||||
if (error < 0) {
|
||||
git_vector_free(&taglist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tag_names->strings = (char **)taglist.contents;
|
||||
tag_names->count = taglist.length;
|
||||
if (error < 0)
|
||||
git_vector_free(&taglist);
|
||||
|
||||
tag_names->strings =
|
||||
(char **)git_vector_detach(&tag_names->count, NULL, &taglist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -93,18 +93,19 @@ static int git_stream_read(
|
||||
size_t buf_size,
|
||||
size_t *bytes_read)
|
||||
{
|
||||
int error;
|
||||
git_stream *s = (git_stream *)stream;
|
||||
gitno_buffer buf;
|
||||
|
||||
*bytes_read = 0;
|
||||
|
||||
if (!s->sent_command && send_command(s) < 0)
|
||||
return -1;
|
||||
if (!s->sent_command && (error = send_command(s)) < 0)
|
||||
return error;
|
||||
|
||||
gitno_buffer_setup(&s->socket, &buf, buffer, buf_size);
|
||||
|
||||
if (gitno_recv(&buf) < 0)
|
||||
return -1;
|
||||
if ((error = gitno_recv(&buf)) < 0)
|
||||
return error;
|
||||
|
||||
*bytes_read = buf.offset;
|
||||
|
||||
@ -116,10 +117,11 @@ static int git_stream_write(
|
||||
const char *buffer,
|
||||
size_t len)
|
||||
{
|
||||
int error;
|
||||
git_stream *s = (git_stream *)stream;
|
||||
|
||||
if (!s->sent_command && send_command(s) < 0)
|
||||
return -1;
|
||||
if (!s->sent_command && (error = send_command(s)) < 0)
|
||||
return error;
|
||||
|
||||
return gitno_send(&s->socket, buffer, len, 0);
|
||||
}
|
||||
@ -140,7 +142,7 @@ static void git_stream_free(git_smart_subtransport_stream *stream)
|
||||
}
|
||||
|
||||
git__free(s->url);
|
||||
git__free(s);
|
||||
git__free(s);
|
||||
}
|
||||
|
||||
static int git_stream_alloc(
|
||||
@ -182,18 +184,21 @@ static int _git_uploadpack_ls(
|
||||
char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
|
||||
const char *stream_url = url;
|
||||
git_stream *s;
|
||||
int error = -1;
|
||||
int error;
|
||||
|
||||
*stream = NULL;
|
||||
|
||||
if (!git__prefixcmp(url, prefix_git))
|
||||
stream_url += strlen(prefix_git);
|
||||
|
||||
if (git_stream_alloc(t, stream_url, cmd_uploadpack, stream) < 0)
|
||||
return -1;
|
||||
if ((error = git_stream_alloc(t, stream_url, cmd_uploadpack, stream)) < 0)
|
||||
return error;
|
||||
|
||||
s = (git_stream *)*stream;
|
||||
|
||||
if (!(error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT))) {
|
||||
if (!(error = gitno_extract_url_parts(
|
||||
&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT))) {
|
||||
|
||||
if (!(error = gitno_connect(&s->socket, host, port, 0)))
|
||||
t->current_stream = s;
|
||||
|
||||
|
||||
@ -382,9 +382,6 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
|
||||
|
||||
static void clear_parser_state(http_subtransport *t)
|
||||
{
|
||||
unsigned i;
|
||||
char *entry;
|
||||
|
||||
http_parser_init(&t->parser, HTTP_RESPONSE);
|
||||
gitno_buffer_setup(&t->socket,
|
||||
&t->parse_buffer,
|
||||
@ -407,10 +404,7 @@ static void clear_parser_state(http_subtransport *t)
|
||||
git__free(t->location);
|
||||
t->location = NULL;
|
||||
|
||||
git_vector_foreach(&t->www_authenticate, i, entry)
|
||||
git__free(entry);
|
||||
|
||||
git_vector_free(&t->www_authenticate);
|
||||
git_vector_free_deep(&t->www_authenticate);
|
||||
}
|
||||
|
||||
static int write_chunk(gitno_socket *socket, const char *buffer, size_t len)
|
||||
|
||||
@ -43,43 +43,43 @@ typedef struct {
|
||||
static int add_ref(transport_local *t, const char *name)
|
||||
{
|
||||
const char peeled[] = "^{}";
|
||||
git_oid head_oid;
|
||||
git_remote_head *head;
|
||||
git_object *obj = NULL, *target = NULL;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
int error;
|
||||
|
||||
error = git_reference_name_to_id(&head_oid, t->repo, name);
|
||||
if (error < 0) {
|
||||
if (!strcmp(name, GIT_HEAD_FILE) && error == GIT_ENOTFOUND) {
|
||||
/* This is actually okay. Empty repos often have a HEAD that
|
||||
* points to a nonexistent "refs/heads/master". */
|
||||
giterr_clear();
|
||||
return 0;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
head = git__calloc(1, sizeof(git_remote_head));
|
||||
GITERR_CHECK_ALLOC(head);
|
||||
|
||||
head->name = git__strdup(name);
|
||||
GITERR_CHECK_ALLOC(head->name);
|
||||
|
||||
error = git_reference_name_to_id(&head->oid, t->repo, name);
|
||||
if (error < 0) {
|
||||
git__free(head->name);
|
||||
git__free(head);
|
||||
if (!strcmp(name, GIT_HEAD_FILE) && error == GIT_ENOTFOUND) {
|
||||
/* This is actually okay. Empty repos often have a HEAD that points to
|
||||
* a nonexistent "refs/heads/master". */
|
||||
giterr_clear();
|
||||
return 0;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
git_oid_cpy(&head->oid, &head_oid);
|
||||
|
||||
if (git_vector_insert(&t->refs, head) < 0)
|
||||
{
|
||||
if ((error = git_vector_insert(&t->refs, head)) < 0) {
|
||||
git__free(head->name);
|
||||
git__free(head);
|
||||
return -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* If it's not a tag, we don't need to try to peel it */
|
||||
if (git__prefixcmp(name, GIT_REFS_TAGS_DIR))
|
||||
return 0;
|
||||
|
||||
if (git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY) < 0)
|
||||
return -1;
|
||||
if ((error = git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY)) < 0)
|
||||
return error;
|
||||
|
||||
head = NULL;
|
||||
|
||||
@ -94,27 +94,24 @@ static int add_ref(transport_local *t, const char *name)
|
||||
/* And if it's a tag, peel it, and add it to the list */
|
||||
head = git__calloc(1, sizeof(git_remote_head));
|
||||
GITERR_CHECK_ALLOC(head);
|
||||
|
||||
if (git_buf_join(&buf, 0, name, peeled) < 0)
|
||||
return -1;
|
||||
|
||||
head->name = git_buf_detach(&buf);
|
||||
|
||||
if (git_tag_peel(&target, (git_tag *) obj) < 0)
|
||||
goto on_error;
|
||||
if (!(error = git_tag_peel(&target, (git_tag *)obj))) {
|
||||
git_oid_cpy(&head->oid, git_object_id(target));
|
||||
|
||||
if ((error = git_vector_insert(&t->refs, head)) < 0) {
|
||||
git__free(head->name);
|
||||
git__free(head);
|
||||
}
|
||||
}
|
||||
|
||||
git_oid_cpy(&head->oid, git_object_id(target));
|
||||
git_object_free(obj);
|
||||
git_object_free(target);
|
||||
|
||||
if (git_vector_insert(&t->refs, head) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
git_object_free(obj);
|
||||
git_object_free(target);
|
||||
return -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int store_refs(transport_local *t)
|
||||
@ -222,7 +219,7 @@ static int local_ls(const git_remote_head ***out, size_t *size, git_transport *t
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = (const git_remote_head **) t->refs.contents;
|
||||
*out = (const git_remote_head **)t->refs.contents;
|
||||
*size = t->refs.length;
|
||||
|
||||
return 0;
|
||||
@ -250,8 +247,9 @@ static int local_negotiate_fetch(
|
||||
git_oid_cpy(&rhead->loid, git_object_id(obj));
|
||||
else if (error != GIT_ENOTFOUND)
|
||||
return error;
|
||||
else
|
||||
giterr_clear();
|
||||
git_object_free(obj);
|
||||
giterr_clear();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -528,7 +526,7 @@ static int local_download_pack(
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0)
|
||||
if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Write the data to the ODB */
|
||||
@ -539,7 +537,7 @@ static int local_download_pack(
|
||||
data.progress_payload = progress_payload;
|
||||
data.writepack = writepack;
|
||||
|
||||
if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) < 0)
|
||||
if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) != 0)
|
||||
goto cleanup;
|
||||
}
|
||||
error = writepack->commit(writepack, stats);
|
||||
|
||||
@ -23,13 +23,13 @@ static int git_smart__recv_cb(gitno_buffer *buf)
|
||||
|
||||
buf->offset += bytes_read;
|
||||
|
||||
if (t->packetsize_cb && !t->cancelled.val)
|
||||
if (t->packetsize_cb(bytes_read, t->packetsize_payload)) {
|
||||
if (t->packetsize_cb && !t->cancelled.val) {
|
||||
error = t->packetsize_cb(bytes_read, t->packetsize_payload);
|
||||
if (error) {
|
||||
git_atomic_set(&t->cancelled, 1);
|
||||
|
||||
giterr_clear();
|
||||
return GIT_EUSER;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)(buf->offset - old_len);
|
||||
}
|
||||
@ -342,7 +342,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
|
||||
t->parent.is_connected = git_smart__is_connected;
|
||||
t->parent.read_flags = git_smart__read_flags;
|
||||
t->parent.cancel = git_smart__cancel;
|
||||
|
||||
|
||||
t->owner = owner;
|
||||
t->rpc = definition->rpc;
|
||||
|
||||
@ -359,7 +359,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
|
||||
if (definition->callback(&t->wrapped, &t->parent) < 0) {
|
||||
git__free(t);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*out = (git_transport *) t;
|
||||
return 0;
|
||||
|
||||
@ -45,7 +45,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
|
||||
error = GIT_EBUFS;
|
||||
|
||||
if (error < 0 && error != GIT_EBUFS)
|
||||
return -1;
|
||||
return error;
|
||||
|
||||
if (error == GIT_EBUFS) {
|
||||
if ((recvd = gitno_recv(buf)) < 0)
|
||||
@ -209,12 +209,13 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
|
||||
git_strarray refs;
|
||||
unsigned int i;
|
||||
git_reference *ref;
|
||||
int error;
|
||||
|
||||
if (git_reference_list(&refs, repo) < 0)
|
||||
return -1;
|
||||
if ((error = git_reference_list(&refs, repo)) < 0)
|
||||
return error;
|
||||
|
||||
if (git_revwalk_new(&walk, repo) < 0)
|
||||
return -1;
|
||||
if ((error = git_revwalk_new(&walk, repo)) < 0)
|
||||
return error;
|
||||
|
||||
git_revwalk_sorting(walk, GIT_SORT_TIME);
|
||||
|
||||
@ -223,13 +224,13 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
|
||||
if (!git__prefixcmp(refs.strings[i], GIT_REFS_TAGS_DIR))
|
||||
continue;
|
||||
|
||||
if (git_reference_lookup(&ref, repo, refs.strings[i]) < 0)
|
||||
if ((error = git_reference_lookup(&ref, repo, refs.strings[i])) < 0)
|
||||
goto on_error;
|
||||
|
||||
if (git_reference_type(ref) == GIT_REF_SYMBOLIC)
|
||||
continue;
|
||||
|
||||
if (git_revwalk_push(walk, git_reference_target(ref)) < 0)
|
||||
if ((error = git_revwalk_push(walk, git_reference_target(ref))) < 0)
|
||||
goto on_error;
|
||||
|
||||
git_reference_free(ref);
|
||||
@ -242,7 +243,7 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
|
||||
on_error:
|
||||
git_reference_free(ref);
|
||||
git_strarray_free(&refs);
|
||||
return -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int wait_while_ack(gitno_buffer *buf)
|
||||
@ -503,7 +504,7 @@ int git_smart__download_pack(
|
||||
}
|
||||
|
||||
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
|
||||
((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0))
|
||||
((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) != 0))
|
||||
goto done;
|
||||
|
||||
/*
|
||||
@ -539,11 +540,9 @@ int git_smart__download_pack(
|
||||
if (pkt->type == GIT_PKT_PROGRESS) {
|
||||
if (t->progress_cb) {
|
||||
git_pkt_progress *p = (git_pkt_progress *) pkt;
|
||||
if (t->progress_cb(p->data, p->len, t->message_cb_payload)) {
|
||||
giterr_clear();
|
||||
error = GIT_EUSER;
|
||||
error = t->progress_cb(p->data, p->len, t->message_cb_payload);
|
||||
if (error)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
git__free(pkt);
|
||||
} else if (pkt->type == GIT_PKT_DATA) {
|
||||
@ -551,7 +550,7 @@ int git_smart__download_pack(
|
||||
error = writepack->append(writepack, p->data, p->len, stats);
|
||||
|
||||
git__free(pkt);
|
||||
if (error < 0)
|
||||
if (error != 0)
|
||||
goto done;
|
||||
} else if (pkt->type == GIT_PKT_FLUSH) {
|
||||
/* A flush indicates the end of the packfile */
|
||||
@ -564,17 +563,15 @@ int git_smart__download_pack(
|
||||
* Trailing execution of progress_cb, if necessary...
|
||||
* Only the callback through the npp datastructure currently
|
||||
* updates the last_fired_bytes value. It is possible that
|
||||
* progress has already been reported with the correct
|
||||
* progress has already been reported with the correct
|
||||
* "received_bytes" value, but until (if?) this is unified
|
||||
* then we will report progress again to be sure that the
|
||||
* correct last received_bytes value is reported.
|
||||
*/
|
||||
if (npp.callback && npp.stats->received_bytes > npp.last_fired_bytes) {
|
||||
if (npp.callback(npp.stats, npp.payload) < 0) {
|
||||
giterr_clear();
|
||||
error = GIT_EUSER;
|
||||
error = npp.callback(npp.stats, npp.payload);
|
||||
if (error != 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
error = writepack->commit(writepack, stats);
|
||||
|
||||
@ -667,9 +667,11 @@ replay:
|
||||
if (allowed_types &&
|
||||
(!t->cred || 0 == (t->cred->credtype & allowed_types))) {
|
||||
|
||||
if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, t->connection_data.user, allowed_types,
|
||||
t->owner->cred_acquire_payload) < 0)
|
||||
return GIT_EUSER;
|
||||
int error = t->owner->cred_acquire_cb(
|
||||
&t->cred, t->owner->url, t->connection_data.user,
|
||||
allowed_types, t->owner->cred_acquire_payload);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
assert(t->cred);
|
||||
|
||||
|
||||
31
src/tree.c
31
src/tree.c
@ -884,22 +884,22 @@ static int tree_walk(
|
||||
git_vector_foreach(&tree->entries, i, entry) {
|
||||
if (preorder) {
|
||||
error = callback(path->ptr, entry, payload);
|
||||
if (error > 0) {
|
||||
if (error < 0) { /* negative value stops iteration */
|
||||
giterr_set_after_callback_function(error, "git_tree_walk");
|
||||
break;
|
||||
}
|
||||
if (error > 0) { /* positive value skips this entry */
|
||||
error = 0;
|
||||
continue;
|
||||
}
|
||||
if (error < 0) {
|
||||
giterr_clear();
|
||||
return GIT_EUSER;
|
||||
}
|
||||
}
|
||||
|
||||
if (git_tree_entry__is_tree(entry)) {
|
||||
git_tree *subtree;
|
||||
size_t path_len = git_buf_len(path);
|
||||
|
||||
if ((error = git_tree_lookup(
|
||||
&subtree, tree->object.repo, &entry->oid)) < 0)
|
||||
error = git_tree_lookup(&subtree, tree->object.repo, &entry->oid);
|
||||
if (error < 0)
|
||||
break;
|
||||
|
||||
/* append the next entry to the path */
|
||||
@ -907,21 +907,24 @@ static int tree_walk(
|
||||
git_buf_putc(path, '/');
|
||||
|
||||
if (git_buf_oom(path))
|
||||
return -1;
|
||||
error = -1;
|
||||
else
|
||||
error = tree_walk(subtree, callback, path, payload, preorder);
|
||||
|
||||
error = tree_walk(subtree, callback, path, payload, preorder);
|
||||
git_tree_free(subtree);
|
||||
|
||||
if (error != 0)
|
||||
break;
|
||||
|
||||
git_buf_truncate(path, path_len);
|
||||
}
|
||||
|
||||
if (!preorder && callback(path->ptr, entry, payload) < 0) {
|
||||
giterr_clear();
|
||||
error = GIT_EUSER;
|
||||
break;
|
||||
if (!preorder) {
|
||||
error = callback(path->ptr, entry, payload);
|
||||
if (error < 0) { /* negative value stops iteration */
|
||||
giterr_set_after_callback_function(error, "git_tree_walk");
|
||||
break;
|
||||
}
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
*/
|
||||
#include <git2/common.h>
|
||||
|
||||
#ifndef GIT_WIN32
|
||||
#if !defined(GIT_WIN32) && !defined(NO_MMAP)
|
||||
|
||||
#include "map.h"
|
||||
#include <sys/mman.h>
|
||||
|
||||
30
src/vector.c
30
src/vector.c
@ -77,6 +77,20 @@ void git_vector_free(git_vector *v)
|
||||
v->_alloc_size = 0;
|
||||
}
|
||||
|
||||
void git_vector_free_deep(git_vector *v)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(v);
|
||||
|
||||
for (i = 0; i < v->length; ++i) {
|
||||
git__free(v->contents[i]);
|
||||
v->contents[i] = NULL;
|
||||
}
|
||||
|
||||
git_vector_free(v);
|
||||
}
|
||||
|
||||
int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp)
|
||||
{
|
||||
assert(v);
|
||||
@ -90,6 +104,22 @@ int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp)
|
||||
return resize_vector(v, max(initial_size, MIN_ALLOCSIZE));
|
||||
}
|
||||
|
||||
void **git_vector_detach(size_t *size, size_t *asize, git_vector *v)
|
||||
{
|
||||
void **data = v->contents;
|
||||
|
||||
if (size)
|
||||
*size = v->length;
|
||||
if (asize)
|
||||
*asize = v->_alloc_size;
|
||||
|
||||
v->_alloc_size = 0;
|
||||
v->length = 0;
|
||||
v->contents = NULL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int git_vector_insert(git_vector *v, void *element)
|
||||
{
|
||||
assert(v);
|
||||
|
||||
@ -23,10 +23,13 @@ typedef struct git_vector {
|
||||
|
||||
int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp);
|
||||
void git_vector_free(git_vector *v);
|
||||
void git_vector_free_deep(git_vector *v); /* free each entry and self */
|
||||
void git_vector_clear(git_vector *v);
|
||||
int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp);
|
||||
void git_vector_swap(git_vector *a, git_vector *b);
|
||||
|
||||
void **git_vector_detach(size_t *size, size_t *asize, git_vector *v);
|
||||
|
||||
void git_vector_sort(git_vector *v);
|
||||
|
||||
/** Linear search for matching entry using internal comparison function */
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "map.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef NO_MMAP
|
||||
|
||||
static DWORD get_page_size(void)
|
||||
{
|
||||
@ -112,4 +113,4 @@ int p_munmap(git_map *map)
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -129,6 +129,8 @@ static int count_attrs(
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CANCEL_VALUE 12345
|
||||
|
||||
static int cancel_iteration(
|
||||
const char *name,
|
||||
const char *value,
|
||||
@ -140,7 +142,7 @@ static int cancel_iteration(
|
||||
*((int *)payload) -= 1;
|
||||
|
||||
if (*((int *)payload) < 0)
|
||||
return -1;
|
||||
return CANCEL_VALUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -166,7 +168,7 @@ void test_attr_repo__foreach(void)
|
||||
|
||||
count = 2;
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_attr_foreach(
|
||||
CANCEL_VALUE, git_attr_foreach(
|
||||
g_repo, 0, "sub/subdir_test1", &cancel_iteration, &count)
|
||||
);
|
||||
}
|
||||
|
||||
@ -486,6 +486,84 @@ void test_checkout_tree__donot_update_deleted_file_by_default(void)
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
struct checkout_cancel_at {
|
||||
const char *filename;
|
||||
int error;
|
||||
int count;
|
||||
};
|
||||
|
||||
static int checkout_cancel_cb(
|
||||
git_checkout_notify_t why,
|
||||
const char *path,
|
||||
const git_diff_file *b,
|
||||
const git_diff_file *t,
|
||||
const git_diff_file *w,
|
||||
void *payload)
|
||||
{
|
||||
struct checkout_cancel_at *ca = payload;
|
||||
|
||||
GIT_UNUSED(why); GIT_UNUSED(b); GIT_UNUSED(t); GIT_UNUSED(w);
|
||||
|
||||
ca->count++;
|
||||
|
||||
if (!strcmp(path, ca->filename))
|
||||
return ca->error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_checkout_tree__can_cancel_checkout_from_notify(void)
|
||||
{
|
||||
struct checkout_cancel_at ca;
|
||||
git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
|
||||
git_oid oid;
|
||||
git_object *obj = NULL;
|
||||
|
||||
assert_on_branch(g_repo, "master");
|
||||
|
||||
cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir"));
|
||||
cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
|
||||
|
||||
ca.filename = "new.txt";
|
||||
ca.error = -5555;
|
||||
ca.count = 0;
|
||||
|
||||
opts.notify_flags = GIT_CHECKOUT_NOTIFY_UPDATED;
|
||||
opts.notify_cb = checkout_cancel_cb;
|
||||
opts.notify_payload = &ca;
|
||||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
cl_assert(!git_path_exists("testrepo/new.txt"));
|
||||
|
||||
cl_git_fail_with(git_checkout_tree(g_repo, obj, &opts), -5555);
|
||||
|
||||
cl_assert(!git_path_exists("testrepo/new.txt"));
|
||||
|
||||
/* on case-insensitive FS = a/b.txt, branch_file.txt, new.txt */
|
||||
/* on case-sensitive FS = README, then above */
|
||||
|
||||
if (git_path_exists("testrepo/.git/CoNfIg")) /* case insensitive */
|
||||
cl_assert_equal_i(3, ca.count);
|
||||
else
|
||||
cl_assert_equal_i(4, ca.count);
|
||||
|
||||
/* and again with a different stopping point and return code */
|
||||
ca.filename = "README";
|
||||
ca.error = 123;
|
||||
ca.count = 0;
|
||||
|
||||
cl_git_fail_with(git_checkout_tree(g_repo, obj, &opts), 123);
|
||||
|
||||
cl_assert(!git_path_exists("testrepo/new.txt"));
|
||||
|
||||
if (git_path_exists("testrepo/.git/CoNfIg")) /* case insensitive */
|
||||
cl_assert_equal_i(4, ca.count);
|
||||
else
|
||||
cl_assert_equal_i(1, ca.count);
|
||||
|
||||
git_object_free(obj);
|
||||
}
|
||||
|
||||
void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void)
|
||||
{
|
||||
git_index *index = NULL;
|
||||
|
||||
@ -22,7 +22,7 @@ void test_clone_nonetwork__initialize(void)
|
||||
memset(&g_options, 0, sizeof(git_clone_options));
|
||||
g_options.version = GIT_CLONE_OPTIONS_VERSION;
|
||||
g_options.checkout_opts = dummy_opts;
|
||||
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
|
||||
g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
|
||||
g_options.remote_callbacks = dummy_callbacks;
|
||||
}
|
||||
|
||||
@ -151,6 +151,61 @@ void test_clone_nonetwork__can_checkout_given_branch(void)
|
||||
|
||||
cl_git_pass(git_repository_head(&g_ref, g_repo));
|
||||
cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test");
|
||||
|
||||
cl_assert(git_path_exists("foo/readme.txt"));
|
||||
}
|
||||
|
||||
static int clone_cancel_fetch_transfer_progress_cb(
|
||||
const git_transfer_progress *stats, void *data)
|
||||
{
|
||||
GIT_UNUSED(stats); GIT_UNUSED(data);
|
||||
return -54321;
|
||||
}
|
||||
|
||||
void test_clone_nonetwork__can_cancel_clone_in_fetch(void)
|
||||
{
|
||||
g_options.checkout_branch = "test";
|
||||
|
||||
g_options.remote_callbacks.transfer_progress =
|
||||
clone_cancel_fetch_transfer_progress_cb;
|
||||
|
||||
cl_git_fail_with(git_clone(
|
||||
&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options),
|
||||
-54321);
|
||||
|
||||
cl_assert(!g_repo);
|
||||
cl_assert(!git_path_exists("foo/readme.txt"));
|
||||
}
|
||||
|
||||
static int clone_cancel_checkout_cb(
|
||||
git_checkout_notify_t why,
|
||||
const char *path,
|
||||
const git_diff_file *b,
|
||||
const git_diff_file *t,
|
||||
const git_diff_file *w,
|
||||
void *payload)
|
||||
{
|
||||
const char *at_file = payload;
|
||||
GIT_UNUSED(why); GIT_UNUSED(b); GIT_UNUSED(t); GIT_UNUSED(w);
|
||||
if (!strcmp(path, at_file))
|
||||
return -12345;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_clone_nonetwork__can_cancel_clone_in_checkout(void)
|
||||
{
|
||||
g_options.checkout_branch = "test";
|
||||
|
||||
g_options.checkout_opts.notify_flags = GIT_CHECKOUT_NOTIFY_UPDATED;
|
||||
g_options.checkout_opts.notify_cb = clone_cancel_checkout_cb;
|
||||
g_options.checkout_opts.notify_payload = "readme.txt";
|
||||
|
||||
cl_git_fail_with(git_clone(
|
||||
&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options),
|
||||
-12345);
|
||||
|
||||
cl_assert(!g_repo);
|
||||
cl_assert(!git_path_exists("foo/readme.txt"));
|
||||
}
|
||||
|
||||
void test_clone_nonetwork__can_detached_head(void)
|
||||
|
||||
@ -247,7 +247,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(GIT_EUSER, ret);
|
||||
cl_assert_equal_i(-100, ret);
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
85
tests/config/rename.c
Normal file
85
tests/config/rename.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "config.h"
|
||||
|
||||
static git_repository *g_repo = NULL;
|
||||
static git_config *g_config = NULL;
|
||||
|
||||
void test_config_rename__initialize(void)
|
||||
{
|
||||
g_repo = cl_git_sandbox_init("testrepo.git");
|
||||
cl_git_pass(git_repository_config(&g_config, g_repo));
|
||||
}
|
||||
|
||||
void test_config_rename__cleanup(void)
|
||||
{
|
||||
git_config_free(g_config);
|
||||
g_config = NULL;
|
||||
|
||||
cl_git_sandbox_cleanup();
|
||||
g_repo = NULL;
|
||||
}
|
||||
|
||||
void test_config_rename__can_rename(void)
|
||||
{
|
||||
const git_config_entry *ce;
|
||||
|
||||
cl_git_pass(git_config_get_entry(
|
||||
&ce, g_config, "branch.track-local.remote"));
|
||||
cl_assert_equal_s(".", ce->value);
|
||||
|
||||
cl_git_fail(git_config_get_entry(
|
||||
&ce, g_config, "branch.local-track.remote"));
|
||||
|
||||
cl_git_pass(git_config_rename_section(
|
||||
g_repo, "branch.track-local", "branch.local-track"));
|
||||
|
||||
cl_git_pass(git_config_get_entry(
|
||||
&ce, g_config, "branch.local-track.remote"));
|
||||
cl_assert_equal_s(".", ce->value);
|
||||
|
||||
cl_git_fail(git_config_get_entry(
|
||||
&ce, g_config, "branch.track-local.remote"));
|
||||
}
|
||||
|
||||
void test_config_rename__prevent_overwrite(void)
|
||||
{
|
||||
const git_config_entry *ce;
|
||||
|
||||
cl_git_pass(git_config_set_string(
|
||||
g_config, "branch.local-track.remote", "yellow"));
|
||||
|
||||
cl_git_pass(git_config_get_entry(
|
||||
&ce, g_config, "branch.local-track.remote"));
|
||||
cl_assert_equal_s("yellow", ce->value);
|
||||
|
||||
cl_git_pass(git_config_rename_section(
|
||||
g_repo, "branch.track-local", "branch.local-track"));
|
||||
|
||||
cl_git_pass(git_config_get_entry(
|
||||
&ce, g_config, "branch.local-track.remote"));
|
||||
cl_assert_equal_s(".", ce->value);
|
||||
|
||||
/* so, we don't currently prevent overwrite... */
|
||||
/* {
|
||||
const git_error *err;
|
||||
cl_assert((err = giterr_last()) != NULL);
|
||||
cl_assert(err->message != NULL);
|
||||
} */
|
||||
}
|
||||
|
||||
static void assert_invalid_config_section_name(
|
||||
git_repository *repo, const char *name)
|
||||
{
|
||||
cl_git_fail_with(
|
||||
git_config_rename_section(repo, "branch.remoteless", name),
|
||||
GIT_EINVALIDSPEC);
|
||||
}
|
||||
|
||||
void test_config_rename__require_a_valid_new_name(void)
|
||||
{
|
||||
assert_invalid_config_section_name(g_repo, "");
|
||||
assert_invalid_config_section_name(g_repo, "bra\nch");
|
||||
assert_invalid_config_section_name(g_repo, "branc#");
|
||||
assert_invalid_config_section_name(g_repo, "bra\nch.duh");
|
||||
assert_invalid_config_section_name(g_repo, "branc#.duh");
|
||||
}
|
||||
@ -46,23 +46,3 @@ void test_config_validkeyname__accessing_requires_a_valid_name(void)
|
||||
assert_invalid_config_key_name("dif.dir\nstat.lines");
|
||||
assert_invalid_config_key_name("dif.dirstat.li\nes");
|
||||
}
|
||||
|
||||
static void assert_invalid_config_section_name(git_repository *repo, const char *name)
|
||||
{
|
||||
cl_git_fail_with(git_config_rename_section(repo, "branch.remoteless", name), GIT_EINVALIDSPEC);
|
||||
}
|
||||
|
||||
void test_config_validkeyname__renaming_a_section_requires_a_valid_name(void)
|
||||
{
|
||||
git_repository *repo;
|
||||
|
||||
cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
|
||||
|
||||
assert_invalid_config_section_name(repo, "");
|
||||
assert_invalid_config_section_name(repo, "bra\nch");
|
||||
assert_invalid_config_section_name(repo, "branc#");
|
||||
assert_invalid_config_section_name(repo, "bra\nch.duh");
|
||||
assert_invalid_config_section_name(repo, "branc#.duh");
|
||||
|
||||
git_repository_free(repo);
|
||||
}
|
||||
|
||||
@ -303,3 +303,4 @@ void test_config_write__updating_a_locked_config_file_returns_ELOCKED(void)
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
|
||||
@ -350,15 +350,26 @@ void test_core_path__10_fromurl(void)
|
||||
|
||||
typedef struct {
|
||||
int expect_idx;
|
||||
int cancel_after;
|
||||
char **expect;
|
||||
} check_walkup_info;
|
||||
|
||||
#define CANCEL_VALUE 1234
|
||||
|
||||
static int check_one_walkup_step(void *ref, git_buf *path)
|
||||
{
|
||||
check_walkup_info *info = (check_walkup_info *)ref;
|
||||
|
||||
if (!info->cancel_after) {
|
||||
cl_assert_equal_s(info->expect[info->expect_idx], "[CANCEL]");
|
||||
return CANCEL_VALUE;
|
||||
}
|
||||
info->cancel_after--;
|
||||
|
||||
cl_assert(info->expect[info->expect_idx] != NULL);
|
||||
cl_assert_equal_s(info->expect[info->expect_idx], path->ptr);
|
||||
info->expect_idx++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -381,6 +392,7 @@ void test_core_path__11_walkup(void)
|
||||
check_walkup_info info;
|
||||
|
||||
info.expect = expect;
|
||||
info.cancel_after = -1;
|
||||
|
||||
for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
|
||||
|
||||
@ -400,6 +412,42 @@ void test_core_path__11_walkup(void)
|
||||
git_buf_free(&p);
|
||||
}
|
||||
|
||||
void test_core_path__11a_walkup_cancel(void)
|
||||
{
|
||||
git_buf p = GIT_BUF_INIT;
|
||||
int cancel[] = { 3, 2, 1, 0 };
|
||||
char *expect[] = {
|
||||
"/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "[CANCEL]", NULL,
|
||||
"/a/b/c/d/e", "/a/b/c/d/", "[CANCEL]", NULL,
|
||||
"/a/b/c/d/e", "[CANCEL]", NULL,
|
||||
"[CANCEL]", NULL,
|
||||
NULL
|
||||
};
|
||||
char *root[] = { NULL, NULL, "/", "", NULL };
|
||||
int i, j;
|
||||
check_walkup_info info;
|
||||
|
||||
info.expect = expect;
|
||||
|
||||
for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
|
||||
|
||||
git_buf_sets(&p, expect[i]);
|
||||
|
||||
info.cancel_after = cancel[j];
|
||||
info.expect_idx = i;
|
||||
|
||||
cl_assert_equal_i(
|
||||
CANCEL_VALUE,
|
||||
git_path_walk_up(&p, root[j], check_one_walkup_step, &info)
|
||||
);
|
||||
|
||||
/* skip to next run of expectations */
|
||||
while (expect[i] != NULL) i++;
|
||||
}
|
||||
|
||||
git_buf_free(&p);
|
||||
}
|
||||
|
||||
void test_core_path__12_offset_to_path_root(void)
|
||||
{
|
||||
cl_assert(git_path_root("non/rooted/path") == -1);
|
||||
|
||||
@ -139,7 +139,8 @@ void test_core_pool__strndup_limit(void)
|
||||
git_pool p;
|
||||
|
||||
cl_git_pass(git_pool_init(&p, 1, 100));
|
||||
cl_assert(git_pool_strndup(&p, "foo", -1) == NULL);
|
||||
/* ensure 64 bit doesn't overflow */
|
||||
cl_assert(git_pool_strndup(&p, "foo", (size_t)-1) == NULL);
|
||||
git_pool_clear(&p);
|
||||
}
|
||||
|
||||
|
||||
@ -128,9 +128,7 @@ void test_diff_index__1(void)
|
||||
cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts));
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER,
|
||||
git_diff_foreach(diff, diff_stop_after_2_files, NULL, NULL, &exp)
|
||||
);
|
||||
1, git_diff_foreach(diff, diff_stop_after_2_files, NULL, NULL, &exp) );
|
||||
|
||||
cl_assert_equal_i(2, exp.files);
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ static int assert_called_notifications(
|
||||
{
|
||||
bool found = false;
|
||||
notify_expected *exp = (notify_expected*)payload;
|
||||
notify_expected *e;;
|
||||
notify_expected *e;
|
||||
|
||||
GIT_UNUSED(diff_so_far);
|
||||
|
||||
@ -182,10 +182,12 @@ void test_diff_notify__notify_cb_can_abort_diff(void)
|
||||
opts.pathspec.count = 1;
|
||||
|
||||
pathspec = "file_deleted";
|
||||
cl_git_fail(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
|
||||
cl_git_fail_with(
|
||||
git_diff_index_to_workdir(&diff, g_repo, NULL, &opts), -42);
|
||||
|
||||
pathspec = "staged_changes_modified_file";
|
||||
cl_git_fail(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
|
||||
cl_git_fail_with(
|
||||
git_diff_index_to_workdir(&diff, g_repo, NULL, &opts), -42);
|
||||
}
|
||||
|
||||
static int filter_all(
|
||||
|
||||
@ -30,8 +30,6 @@ static int check_removal_cb(
|
||||
const git_diff_line *line,
|
||||
void *payload)
|
||||
{
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
switch (line->origin) {
|
||||
case GIT_DIFF_LINE_FILE_HDR:
|
||||
cl_assert_equal_s(EXPECTED_HEADER, line->content);
|
||||
@ -40,10 +38,12 @@ static int check_removal_cb(
|
||||
|
||||
case GIT_DIFF_LINE_HUNK_HDR:
|
||||
cl_assert_equal_s(EXPECTED_HUNK, line->content);
|
||||
/* Fall through */
|
||||
goto check_hunk;
|
||||
|
||||
case GIT_DIFF_LINE_CONTEXT:
|
||||
case GIT_DIFF_LINE_DELETION:
|
||||
if (payload != NULL)
|
||||
return *(int *)payload;
|
||||
goto check_hunk;
|
||||
|
||||
default:
|
||||
@ -101,6 +101,39 @@ void test_diff_patch__can_properly_display_the_removal_of_a_file(void)
|
||||
git_tree_free(one);
|
||||
}
|
||||
|
||||
void test_diff_patch__can_cancel_diff_print(void)
|
||||
{
|
||||
const char *one_sha = "26a125e";
|
||||
const char *another_sha = "735b6a2";
|
||||
git_tree *one, *another;
|
||||
git_diff *diff;
|
||||
int fail_with;
|
||||
|
||||
g_repo = cl_git_sandbox_init("status");
|
||||
|
||||
one = resolve_commit_oid_to_tree(g_repo, one_sha);
|
||||
another = resolve_commit_oid_to_tree(g_repo, another_sha);
|
||||
|
||||
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL));
|
||||
|
||||
fail_with = -2323;
|
||||
|
||||
cl_git_fail_with(git_diff_print(
|
||||
diff, GIT_DIFF_FORMAT_PATCH, check_removal_cb, &fail_with),
|
||||
fail_with);
|
||||
|
||||
fail_with = 45;
|
||||
|
||||
cl_git_fail_with(git_diff_print(
|
||||
diff, GIT_DIFF_FORMAT_PATCH, check_removal_cb, &fail_with),
|
||||
fail_with);
|
||||
|
||||
git_diff_free(diff);
|
||||
|
||||
git_tree_free(another);
|
||||
git_tree_free(one);
|
||||
}
|
||||
|
||||
void test_diff_patch__to_string(void)
|
||||
{
|
||||
const char *one_sha = "26a125e";
|
||||
|
||||
@ -111,6 +111,28 @@ void test_diff_rename__match_oid(void)
|
||||
|
||||
git_diff_free(diff);
|
||||
|
||||
cl_git_pass(git_diff_tree_to_tree(
|
||||
&diff, g_repo, old_tree, new_tree, &diffopts));
|
||||
|
||||
/* git diff --find-copies-harder -M100 -B100 \
|
||||
* 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \
|
||||
* 2bc7f351d20b53f1c72c16c4b036e491c478c49a
|
||||
*/
|
||||
opts.flags = GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED |
|
||||
GIT_DIFF_FIND_EXACT_MATCH_ONLY;
|
||||
cl_git_pass(git_diff_find_similar(diff, &opts));
|
||||
|
||||
memset(&exp, 0, sizeof(exp));
|
||||
cl_git_pass(git_diff_foreach(
|
||||
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
|
||||
|
||||
cl_assert_equal_i(3, exp.files);
|
||||
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]);
|
||||
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]);
|
||||
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]);
|
||||
|
||||
git_diff_free(diff);
|
||||
|
||||
git_tree_free(old_tree);
|
||||
git_tree_free(new_tree);
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "fileops.h"
|
||||
|
||||
git_repository *g_repo = NULL;
|
||||
#define TEST_DIR "addall"
|
||||
|
||||
void test_index_addall__initialize(void)
|
||||
{
|
||||
@ -13,6 +14,8 @@ void test_index_addall__cleanup(void)
|
||||
{
|
||||
git_repository_free(g_repo);
|
||||
g_repo = NULL;
|
||||
|
||||
cl_fixture_cleanup(TEST_DIR);
|
||||
}
|
||||
|
||||
#define STATUS_INDEX_FLAGS \
|
||||
@ -132,6 +135,25 @@ static void check_stat_data(git_index *index, const char *path, bool match)
|
||||
}
|
||||
}
|
||||
|
||||
static void addall_create_test_repo(bool check_every_step)
|
||||
{
|
||||
cl_git_pass(git_repository_init(&g_repo, TEST_DIR, false));
|
||||
if (check_every_step)
|
||||
check_status(g_repo, 0, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
cl_git_mkfile(TEST_DIR "/file.foo", "a file");
|
||||
if (check_every_step)
|
||||
check_status(g_repo, 0, 0, 0, 1, 0, 0, 0);
|
||||
|
||||
cl_git_mkfile(TEST_DIR "/.gitignore", "*.foo\n");
|
||||
if (check_every_step)
|
||||
check_status(g_repo, 0, 0, 0, 1, 0, 0, 1);
|
||||
|
||||
cl_git_mkfile(TEST_DIR "/file.bar", "another file");
|
||||
if (check_every_step)
|
||||
check_status(g_repo, 0, 0, 0, 2, 0, 0, 1);
|
||||
}
|
||||
|
||||
void test_index_addall__repo_lifecycle(void)
|
||||
{
|
||||
int error;
|
||||
@ -139,43 +161,33 @@ void test_index_addall__repo_lifecycle(void)
|
||||
git_strarray paths = { NULL, 0 };
|
||||
char *strs[1];
|
||||
|
||||
cl_git_pass(git_repository_init(&g_repo, "addall", false));
|
||||
check_status(g_repo, 0, 0, 0, 0, 0, 0, 0);
|
||||
addall_create_test_repo(true);
|
||||
|
||||
cl_git_pass(git_repository_index(&index, g_repo));
|
||||
|
||||
cl_git_mkfile("addall/file.foo", "a file");
|
||||
check_status(g_repo, 0, 0, 0, 1, 0, 0, 0);
|
||||
|
||||
cl_git_mkfile("addall/.gitignore", "*.foo\n");
|
||||
check_status(g_repo, 0, 0, 0, 1, 0, 0, 1);
|
||||
|
||||
cl_git_mkfile("addall/file.bar", "another file");
|
||||
check_status(g_repo, 0, 0, 0, 2, 0, 0, 1);
|
||||
|
||||
strs[0] = "file.*";
|
||||
paths.strings = strs;
|
||||
paths.count = 1;
|
||||
|
||||
cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL));
|
||||
check_stat_data(index, "addall/file.bar", true);
|
||||
check_stat_data(index, TEST_DIR "/file.bar", true);
|
||||
check_status(g_repo, 1, 0, 0, 1, 0, 0, 1);
|
||||
|
||||
cl_git_rewritefile("addall/file.bar", "new content for file");
|
||||
check_stat_data(index, "addall/file.bar", false);
|
||||
cl_git_rewritefile(TEST_DIR "/file.bar", "new content for file");
|
||||
check_stat_data(index, TEST_DIR "/file.bar", false);
|
||||
check_status(g_repo, 1, 0, 0, 1, 0, 1, 1);
|
||||
|
||||
cl_git_mkfile("addall/file.zzz", "yet another one");
|
||||
cl_git_mkfile("addall/other.zzz", "yet another one");
|
||||
cl_git_mkfile("addall/more.zzz", "yet another one");
|
||||
cl_git_mkfile(TEST_DIR "/file.zzz", "yet another one");
|
||||
cl_git_mkfile(TEST_DIR "/other.zzz", "yet another one");
|
||||
cl_git_mkfile(TEST_DIR "/more.zzz", "yet another one");
|
||||
check_status(g_repo, 1, 0, 0, 4, 0, 1, 1);
|
||||
|
||||
cl_git_pass(git_index_update_all(index, NULL, NULL, NULL));
|
||||
check_stat_data(index, "addall/file.bar", true);
|
||||
check_stat_data(index, TEST_DIR "/file.bar", true);
|
||||
check_status(g_repo, 1, 0, 0, 4, 0, 0, 1);
|
||||
|
||||
cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL));
|
||||
check_stat_data(index, "addall/file.zzz", true);
|
||||
check_stat_data(index, TEST_DIR "/file.zzz", true);
|
||||
check_status(g_repo, 2, 0, 0, 3, 0, 0, 1);
|
||||
|
||||
cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "first commit");
|
||||
@ -195,27 +207,27 @@ void test_index_addall__repo_lifecycle(void)
|
||||
/* add with force - should allow */
|
||||
cl_git_pass(git_index_add_all(
|
||||
index, &paths, GIT_INDEX_ADD_FORCE, NULL, NULL));
|
||||
check_stat_data(index, "addall/file.foo", true);
|
||||
check_stat_data(index, TEST_DIR "/file.foo", true);
|
||||
check_status(g_repo, 1, 0, 0, 3, 0, 0, 0);
|
||||
|
||||
/* now it's in the index, so regular add should work */
|
||||
cl_git_rewritefile("addall/file.foo", "new content for file");
|
||||
check_stat_data(index, "addall/file.foo", false);
|
||||
cl_git_rewritefile(TEST_DIR "/file.foo", "new content for file");
|
||||
check_stat_data(index, TEST_DIR "/file.foo", false);
|
||||
check_status(g_repo, 1, 0, 0, 3, 0, 1, 0);
|
||||
|
||||
cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL));
|
||||
check_stat_data(index, "addall/file.foo", true);
|
||||
check_stat_data(index, TEST_DIR "/file.foo", true);
|
||||
check_status(g_repo, 1, 0, 0, 3, 0, 0, 0);
|
||||
|
||||
cl_git_pass(git_index_add_bypath(index, "more.zzz"));
|
||||
check_stat_data(index, "addall/more.zzz", true);
|
||||
check_stat_data(index, TEST_DIR "/more.zzz", true);
|
||||
check_status(g_repo, 2, 0, 0, 2, 0, 0, 0);
|
||||
|
||||
cl_git_rewritefile("addall/file.zzz", "new content for file");
|
||||
cl_git_rewritefile(TEST_DIR "/file.zzz", "new content for file");
|
||||
check_status(g_repo, 2, 0, 0, 2, 0, 1, 0);
|
||||
|
||||
cl_git_pass(git_index_add_bypath(index, "file.zzz"));
|
||||
check_stat_data(index, "addall/file.zzz", true);
|
||||
check_stat_data(index, TEST_DIR "/file.zzz", true);
|
||||
check_status(g_repo, 2, 0, 1, 2, 0, 0, 0);
|
||||
|
||||
strs[0] = "*.zzz";
|
||||
@ -228,7 +240,7 @@ void test_index_addall__repo_lifecycle(void)
|
||||
cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "second commit");
|
||||
check_status(g_repo, 0, 0, 0, 3, 0, 0, 0);
|
||||
|
||||
cl_must_pass(p_unlink("addall/file.zzz"));
|
||||
cl_must_pass(p_unlink(TEST_DIR "/file.zzz"));
|
||||
check_status(g_repo, 0, 0, 0, 3, 1, 0, 0);
|
||||
|
||||
/* update_all should be able to remove entries */
|
||||
@ -240,9 +252,9 @@ void test_index_addall__repo_lifecycle(void)
|
||||
check_status(g_repo, 3, 1, 0, 0, 0, 0, 0);
|
||||
|
||||
/* must be able to remove at any position while still updating other files */
|
||||
cl_must_pass(p_unlink("addall/.gitignore"));
|
||||
cl_git_rewritefile("addall/file.zzz", "reconstructed file");
|
||||
cl_git_rewritefile("addall/more.zzz", "altered file reality");
|
||||
cl_must_pass(p_unlink(TEST_DIR "/.gitignore"));
|
||||
cl_git_rewritefile(TEST_DIR "/file.zzz", "reconstructed file");
|
||||
cl_git_rewritefile(TEST_DIR "/more.zzz", "altered file reality");
|
||||
check_status(g_repo, 3, 1, 0, 1, 1, 1, 0);
|
||||
|
||||
cl_git_pass(git_index_update_all(index, NULL, NULL, NULL));
|
||||
@ -256,3 +268,89 @@ void test_index_addall__repo_lifecycle(void)
|
||||
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
static int addall_match_prefix(
|
||||
const char *path, const char *matched_pathspec, void *payload)
|
||||
{
|
||||
GIT_UNUSED(matched_pathspec);
|
||||
return !git__prefixcmp(path, payload) ? 0 : 1;
|
||||
}
|
||||
|
||||
static int addall_match_suffix(
|
||||
const char *path, const char *matched_pathspec, void *payload)
|
||||
{
|
||||
GIT_UNUSED(matched_pathspec);
|
||||
return !git__suffixcmp(path, payload) ? 0 : 1;
|
||||
}
|
||||
|
||||
static int addall_cancel_at(
|
||||
const char *path, const char *matched_pathspec, void *payload)
|
||||
{
|
||||
GIT_UNUSED(matched_pathspec);
|
||||
return !strcmp(path, payload) ? -123 : 0;
|
||||
}
|
||||
|
||||
void test_index_addall__callback_filtering(void)
|
||||
{
|
||||
git_index *index;
|
||||
|
||||
addall_create_test_repo(false);
|
||||
|
||||
cl_git_pass(git_repository_index(&index, g_repo));
|
||||
|
||||
cl_git_pass(
|
||||
git_index_add_all(index, NULL, 0, addall_match_prefix, "file."));
|
||||
check_stat_data(index, TEST_DIR "/file.bar", true);
|
||||
check_status(g_repo, 1, 0, 0, 1, 0, 0, 1);
|
||||
|
||||
cl_git_mkfile(TEST_DIR "/file.zzz", "yet another one");
|
||||
cl_git_mkfile(TEST_DIR "/more.zzz", "yet another one");
|
||||
cl_git_mkfile(TEST_DIR "/other.zzz", "yet another one");
|
||||
|
||||
cl_git_pass(git_index_update_all(index, NULL, NULL, NULL));
|
||||
check_stat_data(index, TEST_DIR "/file.bar", true);
|
||||
check_status(g_repo, 1, 0, 0, 4, 0, 0, 1);
|
||||
|
||||
cl_git_pass(
|
||||
git_index_add_all(index, NULL, 0, addall_match_prefix, "other"));
|
||||
check_stat_data(index, TEST_DIR "/other.zzz", true);
|
||||
check_status(g_repo, 2, 0, 0, 3, 0, 0, 1);
|
||||
|
||||
cl_git_pass(
|
||||
git_index_add_all(index, NULL, 0, addall_match_suffix, ".zzz"));
|
||||
check_status(g_repo, 4, 0, 0, 1, 0, 0, 1);
|
||||
|
||||
cl_git_pass(
|
||||
git_index_remove_all(index, NULL, addall_match_suffix, ".zzz"));
|
||||
check_status(g_repo, 1, 0, 0, 4, 0, 0, 1);
|
||||
|
||||
cl_git_fail_with(
|
||||
git_index_add_all(index, NULL, 0, addall_cancel_at, "more.zzz"), -123);
|
||||
check_status(g_repo, 3, 0, 0, 2, 0, 0, 1);
|
||||
|
||||
cl_git_fail_with(
|
||||
git_index_add_all(index, NULL, 0, addall_cancel_at, "other.zzz"), -123);
|
||||
check_status(g_repo, 4, 0, 0, 1, 0, 0, 1);
|
||||
|
||||
cl_git_pass(
|
||||
git_index_add_all(index, NULL, 0, addall_match_suffix, ".zzz"));
|
||||
check_status(g_repo, 5, 0, 0, 0, 0, 0, 1);
|
||||
|
||||
cl_must_pass(p_unlink(TEST_DIR "/file.zzz"));
|
||||
cl_must_pass(p_unlink(TEST_DIR "/more.zzz"));
|
||||
cl_must_pass(p_unlink(TEST_DIR "/other.zzz"));
|
||||
|
||||
cl_git_fail_with(
|
||||
git_index_update_all(index, NULL, addall_cancel_at, "more.zzz"), -123);
|
||||
/* file.zzz removed from index (so Index Adds 5 -> 4) and
|
||||
* more.zzz + other.zzz removed (so Worktree Dels 0 -> 2) */
|
||||
check_status(g_repo, 4, 0, 0, 0, 2, 0, 1);
|
||||
|
||||
cl_git_fail_with(
|
||||
git_index_update_all(index, NULL, addall_cancel_at, "other.zzz"), -123);
|
||||
/* more.zzz removed from index (so Index Adds 4 -> 3) and
|
||||
* Just other.zzz removed (so Worktree Dels 2 -> 1) */
|
||||
check_status(g_repo, 3, 0, 0, 0, 1, 0, 1);
|
||||
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ void test_notes_notes__can_cancel_foreach(void)
|
||||
create_note(¬e_oid4, "refs/notes/i-can-see-dead-notes", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "I decorate 9fd7 and 4a20\n");
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER,
|
||||
1,
|
||||
git_note_foreach(_repo, "refs/notes/i-can-see-dead-notes",
|
||||
note_cancel_cb, &retrieved_notes));
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ void test_object_blob_fromchunks__doesnot_overwrite_an_already_existing_object(v
|
||||
git_buf content = GIT_BUF_INIT;
|
||||
git_oid expected_oid, oid;
|
||||
int howmany = 7;
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9"));
|
||||
|
||||
cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany));
|
||||
@ -117,3 +117,40 @@ void test_object_blob_fromchunks__creating_a_blob_from_chunks_honors_the_attribu
|
||||
assert_named_chunked_blob("e9671e138a780833cb689753570fd10a55be84fb", "dummy.txt");
|
||||
assert_named_chunked_blob("e9671e138a780833cb689753570fd10a55be84fb", "dummy.dunno");
|
||||
}
|
||||
|
||||
static int failing_chunked_source_cb(
|
||||
char *content, size_t max_length, void *payload)
|
||||
{
|
||||
int *count = (int *)payload;
|
||||
|
||||
GIT_UNUSED(max_length);
|
||||
|
||||
(*count)--;
|
||||
if (*count == 0)
|
||||
return -1234;
|
||||
|
||||
strcpy(content, textual_content);
|
||||
return (int)strlen(textual_content);
|
||||
}
|
||||
|
||||
void test_object_blob_fromchunks__can_stop_with_error(void)
|
||||
{
|
||||
git_oid expected_oid, oid;
|
||||
git_object *blob;
|
||||
int howmany = 7;
|
||||
|
||||
cl_git_pass(git_oid_fromstr(
|
||||
&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9"));
|
||||
|
||||
cl_git_fail_with(
|
||||
git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY),
|
||||
GIT_ENOTFOUND);
|
||||
|
||||
cl_git_fail_with(git_blob_create_fromchunks(
|
||||
&oid, repo, NULL, failing_chunked_source_cb, &howmany), -1234);
|
||||
|
||||
cl_git_fail_with(
|
||||
git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY),
|
||||
GIT_ENOTFOUND);
|
||||
}
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ static int treewalk_stop_cb(
|
||||
|
||||
(*count) += 1;
|
||||
|
||||
return (*count == 2) ? -1 : 0;
|
||||
return (*count == 2) ? -123 : 0;
|
||||
}
|
||||
|
||||
static int treewalk_stop_immediately_cb(
|
||||
@ -83,20 +83,20 @@ void test_object_tree_walk__1(void)
|
||||
|
||||
ct = 0;
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_tree_walk(tree, GIT_TREEWALK_PRE, treewalk_stop_cb, &ct));
|
||||
-123, git_tree_walk(tree, GIT_TREEWALK_PRE, treewalk_stop_cb, &ct));
|
||||
cl_assert_equal_i(2, ct);
|
||||
|
||||
ct = 0;
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_tree_walk(tree, GIT_TREEWALK_POST, treewalk_stop_cb, &ct));
|
||||
-123, git_tree_walk(tree, GIT_TREEWALK_POST, treewalk_stop_cb, &ct));
|
||||
cl_assert_equal_i(2, ct);
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_tree_walk(
|
||||
-100, git_tree_walk(
|
||||
tree, GIT_TREEWALK_PRE, treewalk_stop_immediately_cb, NULL));
|
||||
|
||||
cl_assert_equal_i(
|
||||
GIT_EUSER, git_tree_walk(
|
||||
-100, git_tree_walk(
|
||||
tree, GIT_TREEWALK_POST, treewalk_stop_immediately_cb, NULL));
|
||||
|
||||
git_tree_free(tree);
|
||||
@ -152,7 +152,7 @@ void test_object_tree_walk__2(void)
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.stop = "3.txt";
|
||||
|
||||
cl_assert_equal_i(GIT_EUSER, git_tree_walk(
|
||||
cl_assert_equal_i(-1, git_tree_walk(
|
||||
tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data));
|
||||
cl_assert_equal_i(3, data.files);
|
||||
cl_assert_equal_i(2, data.dirs);
|
||||
@ -168,7 +168,7 @@ void test_object_tree_walk__2(void)
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.stop = "new.txt";
|
||||
|
||||
cl_assert_equal_i(GIT_EUSER, git_tree_walk(
|
||||
cl_assert_equal_i(-1, git_tree_walk(
|
||||
tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data));
|
||||
cl_assert_equal_i(7, data.files);
|
||||
cl_assert_equal_i(4, data.dirs);
|
||||
|
||||
@ -164,24 +164,25 @@ void test_object_tree_write__sorted_subtrees(void)
|
||||
git_treebuilder_free(builder);
|
||||
}
|
||||
|
||||
static struct {
|
||||
unsigned int attr;
|
||||
const char *filename;
|
||||
} _entries[] = {
|
||||
{ GIT_FILEMODE_BLOB, "aardvark" },
|
||||
{ GIT_FILEMODE_BLOB, ".first" },
|
||||
{ GIT_FILEMODE_BLOB, "apple" },
|
||||
{ GIT_FILEMODE_BLOB, "last"},
|
||||
{ GIT_FILEMODE_BLOB, "apple_after"},
|
||||
{ GIT_FILEMODE_BLOB, "after_aardvark"},
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
void test_object_tree_write__removing_and_re_adding_in_treebuilder(void)
|
||||
{
|
||||
git_treebuilder *builder;
|
||||
int i, aardvark_i, apple_i, apple_after_i, apple_extra_i, last_i;
|
||||
int i, aardvark_i, apple_i, apple_after_i, apple_extra_i, last_i;
|
||||
git_oid blank_oid, tree_oid;
|
||||
git_tree *tree;
|
||||
struct {
|
||||
unsigned int attr;
|
||||
const char *filename;
|
||||
} entries[] = {
|
||||
{ GIT_FILEMODE_BLOB, "aardvark" },
|
||||
{ GIT_FILEMODE_BLOB, ".first" },
|
||||
{ GIT_FILEMODE_BLOB, "apple" },
|
||||
{ GIT_FILEMODE_BLOB, "last"},
|
||||
{ GIT_FILEMODE_BLOB, "apple_after"},
|
||||
{ GIT_FILEMODE_BLOB, "after_aardvark"},
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
memset(&blank_oid, 0x0, sizeof(blank_oid));
|
||||
|
||||
@ -189,9 +190,9 @@ void test_object_tree_write__removing_and_re_adding_in_treebuilder(void)
|
||||
|
||||
cl_assert_equal_i(0, (int)git_treebuilder_entrycount(builder));
|
||||
|
||||
for (i = 0; entries[i].filename; ++i)
|
||||
for (i = 0; _entries[i].filename; ++i)
|
||||
cl_git_pass(git_treebuilder_insert(NULL,
|
||||
builder, entries[i].filename, &blank_oid, entries[i].attr));
|
||||
builder, _entries[i].filename, &blank_oid, _entries[i].attr));
|
||||
|
||||
cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder));
|
||||
|
||||
@ -260,3 +261,56 @@ void test_object_tree_write__removing_and_re_adding_in_treebuilder(void)
|
||||
|
||||
git_tree_free(tree);
|
||||
}
|
||||
|
||||
static int treebuilder_filter_prefixed(
|
||||
const git_tree_entry *entry, void *payload)
|
||||
{
|
||||
return !git__prefixcmp(git_tree_entry_name(entry), payload);
|
||||
}
|
||||
|
||||
void test_object_tree_write__filtering(void)
|
||||
{
|
||||
git_treebuilder *builder;
|
||||
int i;
|
||||
git_oid blank_oid, tree_oid;
|
||||
git_tree *tree;
|
||||
|
||||
memset(&blank_oid, 0x0, sizeof(blank_oid));
|
||||
|
||||
cl_git_pass(git_treebuilder_create(&builder, NULL));
|
||||
|
||||
for (i = 0; _entries[i].filename; ++i)
|
||||
cl_git_pass(git_treebuilder_insert(NULL,
|
||||
builder, _entries[i].filename, &blank_oid, _entries[i].attr));
|
||||
|
||||
cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder));
|
||||
|
||||
cl_assert(git_treebuilder_get(builder, "apple") != NULL);
|
||||
cl_assert(git_treebuilder_get(builder, "aardvark") != NULL);
|
||||
cl_assert(git_treebuilder_get(builder, "last") != NULL);
|
||||
|
||||
git_treebuilder_filter(builder, treebuilder_filter_prefixed, "apple");
|
||||
|
||||
cl_assert_equal_i(4, (int)git_treebuilder_entrycount(builder));
|
||||
|
||||
cl_assert(git_treebuilder_get(builder, "apple") == NULL);
|
||||
cl_assert(git_treebuilder_get(builder, "aardvark") != NULL);
|
||||
cl_assert(git_treebuilder_get(builder, "last") != NULL);
|
||||
|
||||
git_treebuilder_filter(builder, treebuilder_filter_prefixed, "a");
|
||||
|
||||
cl_assert_equal_i(2, (int)git_treebuilder_entrycount(builder));
|
||||
|
||||
cl_assert(git_treebuilder_get(builder, "aardvark") == NULL);
|
||||
cl_assert(git_treebuilder_get(builder, "last") != NULL);
|
||||
|
||||
cl_git_pass(git_treebuilder_write(&tree_oid, g_repo, builder));
|
||||
|
||||
git_treebuilder_free(builder);
|
||||
|
||||
cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid));
|
||||
|
||||
cl_assert_equal_i(2, (int)git_tree_entrycount(tree));
|
||||
|
||||
git_tree_free(tree);
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
|
||||
static git_odb *_odb;
|
||||
static git_repository *_repo;
|
||||
static int nobj;
|
||||
|
||||
void test_odb_foreach__cleanup(void)
|
||||
{
|
||||
@ -18,10 +17,10 @@ void test_odb_foreach__cleanup(void)
|
||||
|
||||
static int foreach_cb(const git_oid *oid, void *data)
|
||||
{
|
||||
GIT_UNUSED(data);
|
||||
GIT_UNUSED(oid);
|
||||
int *nobj = data;
|
||||
(*nobj)++;
|
||||
|
||||
nobj++;
|
||||
GIT_UNUSED(oid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -38,43 +37,46 @@ static int foreach_cb(const git_oid *oid, void *data)
|
||||
*/
|
||||
void test_odb_foreach__foreach(void)
|
||||
{
|
||||
int nobj = 0;
|
||||
|
||||
cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
|
||||
git_repository_odb(&_odb, _repo);
|
||||
|
||||
cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL));
|
||||
cl_git_pass(git_odb_foreach(_odb, foreach_cb, &nobj));
|
||||
cl_assert_equal_i(47 + 1640, nobj); /* count + in-pack */
|
||||
}
|
||||
|
||||
void test_odb_foreach__one_pack(void)
|
||||
{
|
||||
git_odb_backend *backend = NULL;
|
||||
int nobj = 0;
|
||||
|
||||
cl_git_pass(git_odb_new(&_odb));
|
||||
cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx")));
|
||||
cl_git_pass(git_odb_add_backend(_odb, backend, 1));
|
||||
_repo = NULL;
|
||||
|
||||
nobj = 0;
|
||||
cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL));
|
||||
cl_git_pass(git_odb_foreach(_odb, foreach_cb, &nobj));
|
||||
cl_assert(nobj == 1628);
|
||||
}
|
||||
|
||||
static int foreach_stop_cb(const git_oid *oid, void *data)
|
||||
{
|
||||
GIT_UNUSED(data);
|
||||
int *nobj = data;
|
||||
(*nobj)++;
|
||||
|
||||
GIT_UNUSED(oid);
|
||||
|
||||
nobj++;
|
||||
|
||||
return (nobj == 1000);
|
||||
return (*nobj == 1000) ? -321 : 0;
|
||||
}
|
||||
|
||||
void test_odb_foreach__interrupt_foreach(void)
|
||||
{
|
||||
nobj = 0;
|
||||
int nobj = 0;
|
||||
|
||||
cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
|
||||
git_repository_odb(&_odb, _repo);
|
||||
|
||||
cl_assert_equal_i(GIT_EUSER, git_odb_foreach(_odb, foreach_stop_cb, NULL));
|
||||
cl_assert_equal_i(-321, git_odb_foreach(_odb, foreach_stop_cb, &nobj));
|
||||
cl_assert(nobj == 1000);
|
||||
}
|
||||
|
||||
@ -273,7 +273,7 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload)
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
if (stats->received_objects > (stats->total_objects/2))
|
||||
return 1;
|
||||
return 4321;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -281,7 +281,8 @@ void test_online_clone__can_cancel(void)
|
||||
{
|
||||
g_options.remote_callbacks.transfer_progress = cancel_at_half;
|
||||
|
||||
cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER);
|
||||
cl_git_fail_with(
|
||||
git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), 4321);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user