diff options
Diffstat (limited to 'include')
51 files changed, 2482 insertions, 640 deletions
diff --git a/include/git2.h b/include/git2.h index d00a20a2e..f74976061 100644 --- a/include/git2.h +++ b/include/git2.h @@ -14,6 +14,7 @@ #include "git2/branch.h" #include "git2/buffer.h" #include "git2/checkout.h" +#include "git2/cherrypick.h" #include "git2/clone.h" #include "git2/commit.h" #include "git2/common.h" @@ -43,6 +44,7 @@ #include "git2/remote.h" #include "git2/repository.h" #include "git2/reset.h" +#include "git2/revert.h" #include "git2/revparse.h" #include "git2/revwalk.h" #include "git2/signature.h" diff --git a/include/git2/attr.h b/include/git2/attr.h index f256ff861..3adbb2c24 100644 --- a/include/git2/attr.h +++ b/include/git2/attr.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, diff --git a/include/git2/blame.h b/include/git2/blame.h index 73bcc5bc6..7f0de1731 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -40,6 +40,9 @@ typedef enum { * commit (like `git blame -CCC`). Implies SAME_COMMIT_COPIES. * NOT IMPLEMENTED. */ GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3), + /** Restrict the search of commits to those reachable following only the + * first parents. */ + GIT_BLAME_FIRST_PARENT = (1<<4), } git_blame_flag_t; /** @@ -80,6 +83,18 @@ typedef struct git_blame_options { #define GIT_BLAME_OPTIONS_INIT {GIT_BLAME_OPTIONS_VERSION} /** + * Initializes a `git_blame_options` with default values. Equivalent to + * creating an instance with GIT_BLAME_OPTIONS_INIT. + * + * @param opts The `git_blame_options` struct to initialize + * @param version Version of struct; pass `GIT_BLAME_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_blame_init_options( + git_blame_options *opts, + unsigned int version); + +/** * Structure that represents a blame hunk. * * - `lines_in_hunk` is the number of lines in this hunk @@ -183,7 +198,7 @@ GIT_EXTERN(int) git_blame_buffer( git_blame **out, git_blame *reference, const char *buffer, - uint32_t buffer_len); + size_t buffer_len); /** * Free memory allocated by git_blame_file or git_blame_buffer. diff --git a/include/git2/blob.h b/include/git2/blob.h index dcab4fbe0..c24ff7e7f 100644 --- a/include/git2/blob.h +++ b/include/git2/blob.h @@ -84,7 +84,7 @@ GIT_EXTERN(git_repository *) git_blob_owner(const git_blob *blob); * time. * * @param blob pointer to the blob - * @return the pointer; NULL if the blob has no contents + * @return the pointer */ GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob); @@ -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, @@ -201,26 +196,27 @@ GIT_EXTERN(int) git_blob_create_fromchunks( /** * Write an in-memory buffer to the ODB as a blob * - * @param oid return the oid of the written blob + * @param id return the id of the written blob * @param repo repository where to blob will be written * @param buffer data to be written into the blob * @param len length of the data * @return 0 or an error code */ -GIT_EXTERN(int) git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len); +GIT_EXTERN(int) git_blob_create_frombuffer( + git_oid *id, git_repository *repo, const void *buffer, size_t len); /** * Determine if the blob content is most certainly binary or not. * * The heuristic used to guess if a file is binary is taken from core git: * Searching for NUL bytes and looking for a reasonable ratio of printable - * to non-printable characters among the first 4000 bytes. + * to non-printable characters among the first 8000 bytes. * * @param blob The blob which content should be analyzed * @return 1 if the content of the blob is detected * as binary; 0 otherwise. */ -GIT_EXTERN(int) git_blob_is_binary(git_blob *blob); +GIT_EXTERN(int) git_blob_is_binary(const git_blob *blob); /** @} */ GIT_END_DECL diff --git a/include/git2/branch.h b/include/git2/branch.h index 44d6fd9c3..f28410000 100644 --- a/include/git2/branch.h +++ b/include/git2/branch.h @@ -43,6 +43,12 @@ GIT_BEGIN_DECL * * @param force Overwrite existing branch. * + * @param signature The identity that will used to populate the reflog entry + * + * @param log_message The one line long message to be appended to the reflog. + * If NULL, the default is "Branch: created"; if you want something more + * useful, provide a message. + * * @return 0, GIT_EINVALIDSPEC or an error code. * A proper reference is written in the refs/heads namespace * pointing to the provided target commit. @@ -52,7 +58,9 @@ GIT_EXTERN(int) git_branch_create( git_repository *repo, const char *branch_name, const git_commit *target, - int force); + int force, + const git_signature *signature, + const char *log_message); /** * Delete an existing branch reference. @@ -76,7 +84,7 @@ typedef struct git_branch_iterator git_branch_iterator; * @param repo Repository where to find the branches. * @param list_flags Filtering flags for the branch * listing. Valid values are GIT_BRANCH_LOCAL, GIT_BRANCH_REMOTE - * or a combination of the two. + * or GIT_BRANCH_ALL. * * @return 0 on success or an error code */ @@ -115,13 +123,19 @@ GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter); * * @param force Overwrite existing branch. * + * @param signature The identity that will used to populate the reflog entry + * + * @param log_message The one line long message to be appended to the reflog + * * @return 0 on success, GIT_EINVALIDSPEC or an error code. */ GIT_EXTERN(int) git_branch_move( git_reference **out, git_reference *branch, const char *new_branch_name, - int force); + int force, + const git_signature *signature, + const char *log_message); /** * Lookup a branch by its name in a repository. @@ -165,8 +179,9 @@ GIT_EXTERN(int) git_branch_lookup( * @return 0 on success; otherwise an error code (e.g., if the * ref is no local or remote branch). */ -GIT_EXTERN(int) git_branch_name(const char **out, - git_reference *ref); +GIT_EXTERN(int) git_branch_name( + const char **out, + const git_reference *ref); /** * Return the reference supporting the remote tracking branch, @@ -182,7 +197,7 @@ GIT_EXTERN(int) git_branch_name(const char **out, */ GIT_EXTERN(int) git_branch_upstream( git_reference **out, - git_reference *branch); + const git_reference *branch); /** * Set the upstream configuration for a given local branch @@ -200,25 +215,20 @@ GIT_EXTERN(int) git_branch_set_upstream(git_reference *branch, const char *upstr * Return the name of the reference supporting the remote tracking branch, * given the name of a local branch reference. * - * @param tracking_branch_name_out The user-allocated buffer which will be - * filled with the name of the reference. Pass NULL if you just want to - * get the needed size of the name of the reference as the output value. - * - * @param buffer_size Size of the `out` buffer in bytes. + * @param out Pointer to the user-allocated git_buf which will be + * filled with the name of the reference. * * @param repo the repository where the branches live * - * @param canonical_branch_name name of the local branch. + * @param refname reference name of the local branch. * - * @return number of characters in the reference name - * including the trailing NUL byte; GIT_ENOTFOUND when no remote tracking - * reference exists, otherwise an error code. + * @return 0, GIT_ENOTFOUND when no remote tracking reference exists, + * otherwise an error code. */ GIT_EXTERN(int) git_branch_upstream_name( - char *tracking_branch_name_out, - size_t buffer_size, + git_buf *out, git_repository *repo, - const char *canonical_branch_name); + const char *refname); /** * Determine if the current local branch is pointed at by HEAD. @@ -229,30 +239,24 @@ GIT_EXTERN(int) git_branch_upstream_name( * error code otherwise. */ GIT_EXTERN(int) git_branch_is_head( - git_reference *branch); + const git_reference *branch); /** * Return the name of remote that the remote tracking branch belongs to. * - * @param remote_name_out The user-allocated buffer which will be - * filled with the name of the remote. Pass NULL if you just want to - * get the needed size of the name of the remote as the output value. - * - * @param buffer_size Size of the `out` buffer in bytes. + * @param out Pointer to the user-allocated git_buf which will be filled iwth the name of the remote. * * @param repo The repository where the branch lives. * * @param canonical_branch_name name of the remote tracking branch. * - * @return Number of characters in the reference name - * including the trailing NUL byte; GIT_ENOTFOUND + * @return 0, GIT_ENOTFOUND * when no remote matching remote was found, * GIT_EAMBIGUOUS when the branch maps to several remotes, * otherwise an error code. */ GIT_EXTERN(int) git_branch_remote_name( - char *remote_name_out, - size_t buffer_size, + git_buf *out, git_repository *repo, const char *canonical_branch_name); diff --git a/include/git2/checkout.h b/include/git2/checkout.h index efafdc3e4..ad44173e6 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -43,17 +43,17 @@ GIT_BEGIN_DECL * In between those are `GIT_CHECKOUT_SAFE` and `GIT_CHECKOUT_SAFE_CREATE` * both of which only make modifications that will not lose changes. * - * | target == baseline | target != baseline | - * ---------------------|-----------------------|----------------------| - * workdir == baseline | no action | create, update, or | - * | | delete file | - * ---------------------|-----------------------|----------------------| - * workdir exists and | no action | conflict (notify | - * is != baseline | notify dirty MODIFIED | and cancel checkout) | - * ---------------------|-----------------------|----------------------| - * workdir missing, | create if SAFE_CREATE | create file | - * baseline present | notify dirty DELETED | | - * ---------------------|-----------------------|----------------------| + * | target == baseline | target != baseline | + * ---------------------|-----------------------|----------------------| + * workdir == baseline | no action | create, update, or | + * | | delete file | + * ---------------------|-----------------------|----------------------| + * workdir exists and | no action | conflict (notify | + * is != baseline | notify dirty MODIFIED | and cancel checkout) | + * ---------------------|-----------------------|----------------------| + * workdir missing, | create if SAFE_CREATE | create file | + * baseline present | notify dirty DELETED | | + * ---------------------|-----------------------|----------------------| * * The only difference between SAFE and SAFE_CREATE is that SAFE_CREATE * will cause a file to be checked out if it is missing from the working @@ -99,9 +99,14 @@ GIT_BEGIN_DECL * files with unmerged index entries instead. GIT_CHECKOUT_USE_OURS and * GIT_CHECKOUT_USE_THEIRS to proceed with the checkout using either the * stage 2 ("ours") or stage 3 ("theirs") version of files in the index. + * + * - GIT_CHECKOUT_DONT_OVERWRITE_IGNORED prevents ignored files from being + * overwritten. Normally, files that are ignored in the working directory + * are not considered "precious" and may be overwritten if the checkout + * target contains that file. */ typedef enum { - GIT_CHECKOUT_NONE = 0, /** default is a dry run, no actual updates */ + GIT_CHECKOUT_NONE = 0, /**< default is a dry run, no actual updates */ /** Allow safe updates that cannot overwrite uncommitted data */ GIT_CHECKOUT_SAFE = (1u << 0), @@ -144,6 +149,15 @@ typedef enum { /** Ignore directories in use, they will be left empty */ GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES = (1u << 18), + /** Don't overwrite ignored files that exist in the checkout target */ + GIT_CHECKOUT_DONT_OVERWRITE_IGNORED = (1u << 19), + + /** Write normal merge files for conflicts */ + GIT_CHECKOUT_CONFLICT_STYLE_MERGE = (1u << 20), + + /** Include common ancestor data in diff3 format files for conflicts */ + GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 = (1u << 21), + /** * THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED */ @@ -174,7 +188,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, @@ -206,12 +225,12 @@ typedef void (*git_checkout_progress_cb)( /** * Checkout options structure * - * Zero out for defaults. Initialize with `GIT_CHECKOUT_OPTS_INIT` macro to + * Zero out for defaults. Initialize with `GIT_CHECKOUT_OPTIONS_INIT` macro to * correctly set the `version` field. E.g. * - * git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + * git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; */ -typedef struct git_checkout_opts { +typedef struct git_checkout_options { unsigned int version; unsigned int checkout_strategy; /** default will be a dry run */ @@ -239,12 +258,25 @@ typedef struct git_checkout_opts { const char *target_directory; /** alternative checkout path to workdir */ + const char *ancestor_label; /** the name of the common ancestor side of conflicts */ const char *our_label; /** the name of the "our" side of conflicts */ const char *their_label; /** the name of the "their" side of conflicts */ -} git_checkout_opts; +} git_checkout_options; + +#define GIT_CHECKOUT_OPTIONS_VERSION 1 +#define GIT_CHECKOUT_OPTIONS_INIT {GIT_CHECKOUT_OPTIONS_VERSION} -#define GIT_CHECKOUT_OPTS_VERSION 1 -#define GIT_CHECKOUT_OPTS_INIT {GIT_CHECKOUT_OPTS_VERSION} +/** +* Initializes a `git_checkout_options` with default values. Equivalent to +* creating an instance with GIT_CHECKOUT_OPTIONS_INIT. +* +* @param opts the `git_checkout_options` struct to initialize. +* @param version Version of struct; pass `GIT_CHECKOUT_OPTIONS_VERSION` +* @return Zero on success; -1 on failure. +*/ +GIT_EXTERN(int) git_checkout_init_options( + git_checkout_options *opts, + unsigned int version); /** * Updates files in the index and the working tree to match the content of @@ -252,13 +284,13 @@ 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, - const git_checkout_opts *opts); + const git_checkout_options *opts); /** * Updates files in the working tree to match the content of the index. @@ -266,13 +298,13 @@ 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, git_index *index, - const git_checkout_opts *opts); + const git_checkout_options *opts); /** * Updates files in the index and working tree to match the content of the @@ -282,13 +314,13 @@ 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, const git_object *treeish, - const git_checkout_opts *opts); + const git_checkout_options *opts); /** @} */ GIT_END_DECL diff --git a/include/git2/cherrypick.h b/include/git2/cherrypick.h new file mode 100644 index 000000000..9eccb0af9 --- /dev/null +++ b/include/git2/cherrypick.h @@ -0,0 +1,87 @@ +/* + * 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. + */ +#ifndef INCLUDE_git_cherrypick_h__ +#define INCLUDE_git_cherrypick_h__ + +#include "common.h" +#include "types.h" +#include "merge.h" + +/** + * @file git2/cherrypick.h + * @brief Git cherry-pick routines + * @defgroup git_cherrypick Git cherry-pick routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +typedef struct { + unsigned int version; + + /** For merge commits, the "mainline" is treated as the parent. */ + unsigned int mainline; + + git_merge_options merge_opts; + git_checkout_options checkout_opts; +} git_cherry_pick_options; + +#define GIT_CHERRY_PICK_OPTIONS_VERSION 1 +#define GIT_CHERRY_PICK_OPTIONS_INIT {GIT_CHERRY_PICK_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT} + +/** + * Initializes a `git_cherry_pick_options` with default values. Equivalent to + * creating an instance with GIT_CHERRY_PICK_OPTIONS_INIT. + * + * @param opts the `git_cherry_pick_options` struct to initialize + * @param version Version of struct; pass `GIT_CHERRY_PICK_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_cherry_pick_init_options( + git_cherry_pick_options *opts, + unsigned int version); + +/** + * Cherry-picks the given commit against the given "our" commit, producing an + * index that reflects the result of the cherry-pick. + * + * The returned index must be freed explicitly with `git_index_free`. + * + * @param out pointer to store the index result in + * @param repo the repository that contains the given commits + * @param cherry_pick_commit the commit to cherry-pick + * @param our_commit the commit to revert against (eg, HEAD) + * @param mainline the parent of the revert commit, if it is a merge + * @param merge_options the merge options (or null for defaults) + * @return zero on success, -1 on failure. + */ +GIT_EXTERN(int) git_cherry_pick_commit( + git_index **out, + git_repository *repo, + git_commit *cherry_pick_commit, + git_commit *our_commit, + unsigned int mainline, + const git_merge_options *merge_options); + +/** + * Cherry-pick the given commit, producing changes in the index and working directory. + * + * @param repo the repository to cherry-pick + * @param commit the commit to cherry-pick + * @param cherry_pick_options the cherry-pick options (or null for defaults) + * @return zero on success, -1 on failure. + */ +GIT_EXTERN(int) git_cherry_pick( + git_repository *repo, + git_commit *commit, + const git_cherry_pick_options *cherry_pick_options); + +/** @} */ +GIT_END_DECL + +#endif + diff --git a/include/git2/clone.h b/include/git2/clone.h index 331cf92e7..05b7522ce 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -24,41 +24,108 @@ GIT_BEGIN_DECL /** + * Options for bypassing the git-aware transport on clone. Bypassing + * it means that instead of a fetch, libgit2 will copy the object + * database directory instead of figuring out what it needs, which is + * faster. If possible, it will hardlink the files to save space. + */ +typedef enum { + /** + * Auto-detect (default), libgit2 will bypass the git-aware + * transport for local paths, but use a normal fetch for + * `file://` urls. + */ + GIT_CLONE_LOCAL_AUTO, + /** + * Bypass the git-aware transport even for a `file://` url. + */ + GIT_CLONE_LOCAL, + /** + * Do no bypass the git-aware transport + */ + GIT_CLONE_NO_LOCAL, + /** + * Bypass the git-aware transport, but do not try to use + * hardlinks. + */ + GIT_CLONE_LOCAL_NO_LINKS, +} git_clone_local_t; + +/** * 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. - * - * ** "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. */ typedef struct git_clone_options { unsigned int version; - git_checkout_opts checkout_opts; + /** + * These options are 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. + */ + git_checkout_options checkout_opts; + + /** + * Callbacks to use for reporting fetch progress. + */ git_remote_callbacks remote_callbacks; + /** + * Set to zero (false) to create a standard repo, or non-zero + * for a bare repo + */ int bare; + + /** + * Set to 1 if errors validating the remote host's certificate + * should be ignored. + */ int ignore_cert_errors; + + /** + * Whether to use a fetch or copy the object database. + */ + git_clone_local_t local; + + /** + * The name to be given to the remote that will be + * created. The default is "origin". + */ const char *remote_name; + + /** + * The name of the branch to checkout. NULL means use the + * remote's default branch. + */ const char* checkout_branch; + + /** + * The identity used when updating the reflog. NULL means to + * use the default signature using the config. + */ + git_signature *signature; } git_clone_options; #define GIT_CLONE_OPTIONS_VERSION 1 -#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}, GIT_REMOTE_CALLBACKS_INIT} +#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE_CREATE}, GIT_REMOTE_CALLBACKS_INIT} + +/** + * Initializes a `git_clone_options` with default values. Equivalent to + * creating an instance with GIT_CLONE_OPTIONS_INIT. + * + * @param opts The `git_clone_options` struct to initialize + * @param version Version of struct; pass `GIT_CLONE_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_clone_init_options( + git_clone_options *opts, + unsigned int version); /** * Clone a remote repository. @@ -70,16 +137,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 +159,48 @@ 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 + * @param signature The identity used when updating the reflog. + * @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_options *co_opts, + const char *branch, + const git_signature *signature); + +/** + * Perform a local clone into a repository + * + * A "local clone" bypasses any git-aware protocols and simply copies + * over the object database from the source repository. It is often + * faster than a git-aware clone, but no verification of the data is + * performed, and can copy over too much data. + * + * @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 + * @param link wether to use hardlinks instead of copying + * objects. This is only possible if both repositories are on the same + * filesystem. + * @param signature the identity used when updating the reflog + * @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_local_into( + git_repository *repo, + git_remote *remote, + const git_checkout_options *co_opts, + const char *branch, + int link, + const git_signature *signature); /** @} */ GIT_END_DECL diff --git a/include/git2/commit.h b/include/git2/commit.h index a08cf1c6c..fb53a701b 100644 --- a/include/git2/commit.h +++ b/include/git2/commit.h @@ -117,6 +117,17 @@ GIT_EXTERN(const char *) git_commit_message(const git_commit *commit); GIT_EXTERN(const char *) git_commit_message_raw(const git_commit *commit); /** + * Get the short "summary" of the git commit message. + * + * The returned message is the summary of the commit, comprising the + * first paragraph of the message with whitespace trimmed and squashed. + * + * @param commit a previously loaded commit. + * @return the summary of a commit or NULL on error + */ +GIT_EXTERN(const char *) git_commit_summary(git_commit *commit); + +/** * Get the commit time (i.e. committer time) of a commit. * * @param commit a previously loaded commit. @@ -231,8 +242,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor( /** * Create new commit in the repository from a list of `git_object` pointers * - * The message will not be cleaned up automatically. You can do that with - * the `git_message_prettify()` function. + * The message will **not** be cleaned up automatically. You can do that + * with the `git_message_prettify()` function. * * @param id Pointer in which to store the OID of the newly created commit * @@ -243,7 +254,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor( * is not direct, it will be resolved to a direct reference. * Use "HEAD" to update the HEAD of the current branch and * make it point to this commit. If the reference doesn't - * exist yet, it will be created. + * exist yet, it will be created. If it does exist, the first + * parent must be the tip of this branch. * * @param author Signature with author and author time of commit * @@ -280,20 +292,20 @@ GIT_EXTERN(int) git_commit_create( const char *message_encoding, const char *message, const git_tree *tree, - int parent_count, + size_t parent_count, const git_commit *parents[]); /** * Create new commit in the repository using a variable argument list. * - * The message will be cleaned up from excess whitespace and it will be made - * sure that the last line ends with a '\n'. + * The message will **not** be cleaned up automatically. You can do that + * with the `git_message_prettify()` function. * * The parents for the commit are specified as a variable list of pointers * to `const git_commit *`. Note that this is a convenience method which may * not be safe to export for certain languages or compilers * - * All other parameters remain the same at `git_commit_create()`. + * All other parameters remain the same as `git_commit_create()`. * * @see git_commit_create */ @@ -306,9 +318,40 @@ GIT_EXTERN(int) git_commit_create_v( const char *message_encoding, const char *message, const git_tree *tree, - int parent_count, + size_t parent_count, ...); +/** + * Amend an existing commit by replacing only non-NULL values. + * + * This creates a new commit that is exactly the same as the old commit, + * except that any non-NULL values will be updated. The new commit has + * the same parents as the old commit. + * + * The `update_ref` value works as in the regular `git_commit_create()`, + * updating the ref to point to the newly rewritten commit. If you want + * to amend a commit that is not currently the tip of the branch and then + * rewrite the following commits to reach a ref, pass this as NULL and + * update the rest of the commit chain and ref separately. + * + * Unlike `git_commit_create()`, the `author`, `committer`, `message`, + * `message_encoding`, and `tree` parameters can be NULL in which case this + * will use the values from the original `commit_to_amend`. + * + * All parameters have the same meanings as in `git_commit_create()`. + * + * @see git_commit_create + */ +GIT_EXTERN(int) git_commit_amend( + git_oid *id, + const git_commit *commit_to_amend, + const char *update_ref, + const git_signature *author, + const git_signature *committer, + const char *message_encoding, + const char *message, + const git_tree *tree); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/common.h b/include/git2/common.h index dca0c9c21..32237efed 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -37,13 +37,6 @@ # define GIT_EXTERN(type) extern type #endif -/** Declare a function as always inlined. */ -#if defined(_MSC_VER) -# define GIT_INLINE(type) static __inline type -#else -# define GIT_INLINE(type) static inline type -#endif - /** Declare a function's takes printf style arguments. */ #ifdef __GNUC__ # define GIT_FORMAT_PRINTF(a,b) __attribute__((format (printf, a, b))) @@ -101,29 +94,34 @@ GIT_BEGIN_DECL GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev); /** - * Combinations of these values describe the capabilities of libgit2. + * Combinations of these values describe the features with which libgit2 + * was compiled */ typedef enum { - GIT_CAP_THREADS = ( 1 << 0 ), - GIT_CAP_HTTPS = ( 1 << 1 ), - GIT_CAP_SSH = ( 1 << 2 ), -} git_cap_t; + GIT_FEATURE_THREADS = (1 << 0), + GIT_FEATURE_HTTPS = (1 << 1), + GIT_FEATURE_SSH = (1 << 2), +} git_feature_t; /** * Query compile time options for libgit2. * - * @return A combination of GIT_CAP_* values. + * @return A combination of GIT_FEATURE_* values. * - * - GIT_CAP_THREADS + * - GIT_FEATURE_THREADS * Libgit2 was compiled with thread support. Note that thread support is * still to be seen as a 'work in progress' - basic object lookups are * believed to be threadsafe, but other operations may not be. * - * - GIT_CAP_HTTPS + * - GIT_FEATURE_HTTPS * Libgit2 supports the https:// protocol. This requires the openssl * library to be found when compiling libgit2. + * + * - GIT_FEATURE_SSH + * Libgit2 supports the SSH protocol for network operations. This requires + * the libssh2 library to be found when compiling libgit2 */ -GIT_EXTERN(int) git_libgit2_capabilities(void); +GIT_EXTERN(int) git_libgit2_features(void); typedef enum { @@ -163,12 +161,12 @@ typedef enum { * >Set the maximum amount of memory that can be mapped at any time * by the library * - * * opts(GIT_OPT_GET_SEARCH_PATH, int level, char *out, size_t len) + * * opts(GIT_OPT_GET_SEARCH_PATH, int level, git_buf *buf) * * > Get the search path for a given level of config data. "level" must * > be one of `GIT_CONFIG_LEVEL_SYSTEM`, `GIT_CONFIG_LEVEL_GLOBAL`, or * > `GIT_CONFIG_LEVEL_XDG`. The search path is written to the `out` - * > buffer up to size `len`. Returns GIT_EBUFS if buffer is too small. + * > buffer. * * * opts(GIT_OPT_SET_SEARCH_PATH, int level, const char *path) * @@ -197,7 +195,7 @@ typedef enum { * > across all repositories before libgit2 starts evicting objects * > from the cache. This is a soft limit, in that the library might * > briefly exceed it, but will start aggressively evicting objects - * > from cache when that happens. The default cache size is 256Mb. + * > from cache when that happens. The default cache size is 256MB. * * * opts(GIT_OPT_ENABLE_CACHING, int enabled) * @@ -212,11 +210,10 @@ typedef enum { * > Get the current bytes in cache and the maximum that would be * > allowed in the cache. * - * * opts(GIT_OPT_GET_TEMPLATE_PATH, char *out, size_t len) + * * opts(GIT_OPT_GET_TEMPLATE_PATH, git_buf *out) * * > Get the default template path. - * > The path is written to the `out` - * > buffer up to size `len`. Returns GIT_EBUFS if buffer is too small. + * > The path is written to the `out` buffer. * * * opts(GIT_OPT_SET_TEMPLATE_PATH, const char *path) * diff --git a/include/git2/config.h b/include/git2/config.h index 95da4bc03..21a5825a5 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -9,6 +9,7 @@ #include "common.h" #include "types.h" +#include "buffer.h" /** * @file git2/config.h @@ -90,11 +91,10 @@ typedef struct { * This method will not guess the path to the xdg compatible * config file (.config/git/config). * - * @param out Buffer to store the path in - * @param length size of the buffer in bytes - * @return 0 if a global configuration file has been found. Its path will be stored in `buffer`. + * @param out Pointer to a user-allocated git_buf in which to store the path + * @return 0 if a global configuration file has been found. Its path will be stored in `out`. */ -GIT_EXTERN(int) git_config_find_global(char *out, size_t length); +GIT_EXTERN(int) git_config_find_global(git_buf *out); /** * Locate the path to the global xdg compatible configuration file @@ -107,25 +107,23 @@ GIT_EXTERN(int) git_config_find_global(char *out, size_t length); * may be used on any `git_config` call to load the * xdg compatible configuration file. * - * @param out Buffer to store the path in - * @param length size of the buffer in bytes + * @param out Pointer to a user-allocated git_buf in which to store the path * @return 0 if a xdg compatible configuration file has been - * found. Its path will be stored in `buffer`. + * found. Its path will be stored in `out`. */ -GIT_EXTERN(int) git_config_find_xdg(char *out, size_t length); +GIT_EXTERN(int) git_config_find_xdg(git_buf *out); /** * Locate the path to the system configuration file * * If /etc/gitconfig doesn't exist, it will look for * %PROGRAMFILES%\Git\etc\gitconfig. - - * @param out Buffer to store the path in - * @param length size of the buffer in bytes + * + * @param out Pointer to a user-allocated git_buf in which to store the path * @return 0 if a system configuration file has been - * found. Its path will be stored in `buffer`. + * found. Its path will be stored in `out`. */ -GIT_EXTERN(int) git_config_find_system(char *out, size_t length); +GIT_EXTERN(int) git_config_find_system(git_buf *out); /** * Open the global, XDG and system configuration files @@ -228,6 +226,22 @@ GIT_EXTERN(int) git_config_open_level( */ GIT_EXTERN(int) git_config_open_global(git_config **out, git_config *config); +/** + * Create a snapshot of the configuration + * + * Create a snapshot of the current state of a configuration, which + * allows you to look into a consistent view of the configuration for + * looking up complex values (e.g. a remote, submodule). + * + * The string returned when querying such a config object is valid + * until it is freed. + * + * @param out pointer in which to store the snapshot config object + * @param config configuration to snapshot + * @return 0 or an error code + */ +GIT_EXTERN(int) git_config_snapshot(git_config **out, git_config *config); + /** * Reload changed config files @@ -314,7 +328,8 @@ GIT_EXTERN(int) git_config_get_bool(int *out, const git_config *cfg, const char * Get the value of a string config variable. * * The string is owned by the variable and should not be freed by the - * user. + * user. The pointer will be valid until the next operation on this + * config object. * * All config files will be looked into, in the order of their * defined level. A higher level means a higher priority. The @@ -355,6 +370,9 @@ GIT_EXTERN(int) git_config_multivar_iterator_new(git_config_iterator **out, cons /** * Return the current entry and advance the iterator * + * The pointers returned by this function are valid until the iterator + * is freed. + * * @param entry pointer to store the entry * @param iter the iterator * @return 0 or an error code. GIT_ITEROVER if the iteration has completed @@ -450,13 +468,16 @@ 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. + * + * The pointers passed to the callback are only valid as long as the + * iteration is ongoing. * * @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, @@ -493,6 +514,9 @@ GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const gi * regular expression that filters which config keys are passed to the * callback. * + * The pointers passed to the callback are only valid as long as the + * iteration is ongoing. + * * @param cfg where to get the variables from * @param regexp regular expression to match against config names * @param callback the function to call on each variable @@ -612,8 +636,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); /** @} */ diff --git a/include/git2/diff.h b/include/git2/diff.h index 61d288380..675c209be 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -145,6 +145,13 @@ typedef enum { */ GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = (1u << 14), + /** When diff finds a file in the working directory with stat + * information different from the index, but the OID ends up being the + * same, write the correct stat information into the index. Note: + * without this flag, diff will always leave the index untouched. + */ + GIT_DIFF_UPDATE_INDEX = (1u << 15), + /* * Options controlling how output will be generated */ @@ -180,6 +187,10 @@ typedef enum { /** Take extra time to find minimal diff */ GIT_DIFF_MINIMAL = (1 << 29), + /** Include the necessary deflate / delta information so that `git-apply` + * can apply given diff information to binary files. + */ + GIT_DIFF_SHOW_BINARY = (1 << 30), } git_diff_option_t; /** @@ -201,9 +212,9 @@ typedef struct git_diff git_diff; * considered reserved for internal or future use. */ typedef enum { - GIT_DIFF_FLAG_BINARY = (1u << 0), /** file(s) treated as binary data */ - GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /** file(s) treated as text data */ - GIT_DIFF_FLAG_VALID_OID = (1u << 2), /** `oid` value is known correct */ + GIT_DIFF_FLAG_BINARY = (1u << 0), /**< file(s) treated as binary data */ + GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /**< file(s) treated as text data */ + GIT_DIFF_FLAG_VALID_ID = (1u << 2), /**< `id` value is known correct */ } git_diff_flag_t; /** @@ -217,15 +228,15 @@ typedef enum { * DELETED pairs). */ typedef enum { - GIT_DELTA_UNMODIFIED = 0, /** no changes */ - GIT_DELTA_ADDED = 1, /** entry does not exist in old version */ - GIT_DELTA_DELETED = 2, /** entry does not exist in new version */ - GIT_DELTA_MODIFIED = 3, /** entry content changed between old and new */ - GIT_DELTA_RENAMED = 4, /** entry was renamed between old and new */ - GIT_DELTA_COPIED = 5, /** entry was copied from another old entry */ - GIT_DELTA_IGNORED = 6, /** entry is ignored item in workdir */ - GIT_DELTA_UNTRACKED = 7, /** entry is untracked item in workdir */ - GIT_DELTA_TYPECHANGE = 8, /** type of entry changed between old and new */ + GIT_DELTA_UNMODIFIED = 0, /**< no changes */ + GIT_DELTA_ADDED = 1, /**< entry does not exist in old version */ + GIT_DELTA_DELETED = 2, /**< entry does not exist in new version */ + GIT_DELTA_MODIFIED = 3, /**< entry content changed between old and new */ + GIT_DELTA_RENAMED = 4, /**< entry was renamed between old and new */ + GIT_DELTA_COPIED = 5, /**< entry was copied from another old entry */ + GIT_DELTA_IGNORED = 6, /**< entry is ignored item in workdir */ + GIT_DELTA_UNTRACKED = 7, /**< entry is untracked item in workdir */ + GIT_DELTA_TYPECHANGE = 8, /**< type of entry changed between old and new */ } git_delta_t; /** @@ -250,7 +261,7 @@ typedef enum { * be restricted to one of the `git_filemode_t` values. */ typedef struct { - git_oid oid; + git_oid id; const char *path; git_off_t size; uint32_t flags; @@ -361,7 +372,7 @@ typedef struct { uint16_t context_lines; /**< defaults to 3 */ uint16_t interhunk_lines; /**< defaults to 0 */ - uint16_t oid_abbrev; /**< default 'core.abbrev' or 7 if unset */ + uint16_t id_abbrev; /**< default 'core.abbrev' or 7 if unset */ git_off_t max_size; /**< defaults to 512MB */ const char *old_prefix; /**< defaults to "a" */ const char *new_prefix; /**< defaults to "b" */ @@ -377,6 +388,18 @@ typedef struct { {GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_DEFAULT, {NULL,0}, NULL, NULL, 3} /** + * Initializes a `git_diff_options` with default values. Equivalent to + * creating an instance with GIT_DIFF_OPTIONS_INIT. + * + * @param opts The `git_diff_options` struct to initialize + * @param version Version of struct; pass `GIT_DIFF_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_diff_init_options( + git_diff_options *opts, + unsigned int version); + +/** * When iterating over a diff, callback that will be made per file. * * @param delta A pointer to the delta data for the file @@ -393,12 +416,12 @@ typedef int (*git_diff_file_cb)( */ typedef struct git_diff_hunk git_diff_hunk; struct git_diff_hunk { - int old_start; /** Starting line number in old_file */ - int old_lines; /** Number of lines in old_file */ - int new_start; /** Starting line number in new_file */ - int new_lines; /** Number of lines in new_file */ - size_t header_len; /** Number of bytes in header text */ - char header[128]; /** Header text, NUL-byte terminated */ + int old_start; /**< Starting line number in old_file */ + int old_lines; /**< Number of lines in old_file */ + int new_start; /**< Starting line number in new_file */ + int new_lines; /**< Number of lines in new_file */ + size_t header_len; /**< Number of bytes in header text */ + char header[128]; /**< Header text, NUL-byte terminated */ }; /** @@ -441,13 +464,13 @@ typedef enum { */ typedef struct git_diff_line git_diff_line; struct git_diff_line { - char origin; /** A git_diff_line_t value */ - int old_lineno; /** Line number in old file or -1 for added line */ - int new_lineno; /** Line number in new file or -1 for deleted line */ - int num_lines; /** Number of newline characters in content */ - size_t content_len; /** Number of bytes of data */ - git_off_t content_offset; /** Offset in the original file to the content */ - const char *content; /** Pointer to diff text, not NUL-byte terminated */ + char origin; /**< A git_diff_line_t value */ + int old_lineno; /**< Line number in old file or -1 for added line */ + int new_lineno; /**< Line number in new file or -1 for deleted line */ + int num_lines; /**< Number of newline characters in content */ + size_t content_len; /**< Number of bytes of data */ + git_off_t content_offset; /**< Offset in the original file to the content */ + const char *content; /**< Pointer to diff text, not NUL-byte terminated */ }; /** @@ -459,50 +482,83 @@ struct git_diff_line { * of lines of file and hunk headers. */ typedef int (*git_diff_line_cb)( - const git_diff_delta *delta, /** delta that contains this data */ - const git_diff_hunk *hunk, /** hunk containing this data */ - const git_diff_line *line, /** line data */ - void *payload); /** user reference data */ + const git_diff_delta *delta, /**< delta that contains this data */ + const git_diff_hunk *hunk, /**< hunk containing this data */ + const git_diff_line *line, /**< line data */ + void *payload); /**< user reference data */ /** * Flags to control the behavior of diff rename/copy detection. */ typedef enum { - /** look for renames? (`--find-renames`) */ + /** Obey `diff.renames`. Overridden by any other GIT_DIFF_FIND_... flag. */ + GIT_DIFF_FIND_BY_CONFIG = 0, + + /** Look for renames? (`--find-renames`) */ GIT_DIFF_FIND_RENAMES = (1u << 0), - /** consider old side of modified for renames? (`--break-rewrites=N`) */ + + /** Consider old side of MODIFIED for renames? (`--break-rewrites=N`) */ GIT_DIFF_FIND_RENAMES_FROM_REWRITES = (1u << 1), - /** look for copies? (a la `--find-copies`) */ + /** Look for copies? (a la `--find-copies`). */ GIT_DIFF_FIND_COPIES = (1u << 2), - /** consider unmodified as copy sources? (`--find-copies-harder`) */ + + /** Consider UNMODIFIED as copy sources? (`--find-copies-harder`). + * + * For this to work correctly, use GIT_DIFF_INCLUDE_UNMODIFIED when + * the initial `git_diff` is being generated. + */ GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED = (1u << 3), - /** mark large rewrites for split (`--break-rewrites=/M`) */ + /** Mark significant rewrites for split (`--break-rewrites=/M`) */ GIT_DIFF_FIND_REWRITES = (1u << 4), - /** actually split large rewrites into delete/add pairs */ + /** Actually split large rewrites into delete/add pairs */ GIT_DIFF_BREAK_REWRITES = (1u << 5), - /** mark rewrites for split and break into delete/add pairs */ + /** Mark rewrites for split and break into delete/add pairs */ GIT_DIFF_FIND_AND_BREAK_REWRITES = (GIT_DIFF_FIND_REWRITES | GIT_DIFF_BREAK_REWRITES), - /** find renames/copies for untracked items in working directory */ + /** Find renames/copies for UNTRACKED items in working directory. + * + * For this to work correctly, use GIT_DIFF_INCLUDE_UNTRACKED when the + * initial `git_diff` is being generated (and obviously the diff must + * be against the working directory for this to make sense). + */ GIT_DIFF_FIND_FOR_UNTRACKED = (1u << 6), - /** turn on all finding features */ + /** Turn on all finding features. */ GIT_DIFF_FIND_ALL = (0x0ff), - /** measure similarity ignoring leading whitespace (default) */ + /** Measure similarity ignoring leading whitespace (default) */ GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE = 0, - /** measure similarity ignoring all whitespace */ + /** Measure similarity ignoring all whitespace */ GIT_DIFF_FIND_IGNORE_WHITESPACE = (1u << 12), - /** measure similarity including all data */ + /** Measure similarity including all data */ GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE = (1u << 13), - /** measure similarity only by comparing SHAs (fast and cheap) */ + /** Measure similarity only by comparing SHAs (fast and cheap) */ GIT_DIFF_FIND_EXACT_MATCH_ONLY = (1u << 14), - /** do not break rewrites unless they contribute to a rename */ + /** Do not break rewrites unless they contribute to a rename. + * + * Normally, GIT_DIFF_FIND_AND_BREAK_REWRITES will measure the self- + * similarity of modified files and split the ones that have changed a + * lot into a DELETE / ADD pair. Then the sides of that pair will be + * considered candidates for rename and copy detection. + * + * If you add this flag in and the split pair is *not* used for an + * actual rename or copy, then the modified record will be restored to + * a regular MODIFIED record instead of being split. + */ GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY = (1u << 15), + + /** Remove any UNMODIFIED deltas after find_similar is done. + * + * Using GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED to emulate the + * --find-copies-harder behavior requires building a diff with the + * GIT_DIFF_INCLUDE_UNMODIFIED flag. If you do not want UNMODIFIED + * records in the final result, pass this flag to have them removed. + */ + GIT_DIFF_FIND_REMOVE_UNMODIFIED = (1u << 16), } git_diff_find_t; /** @@ -543,7 +599,11 @@ typedef struct { typedef struct { unsigned int version; - /** Combination of git_diff_find_t values (default FIND_RENAMES) */ + /** + * 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; /** Similarity to consider a file renamed (default 50) */ @@ -567,6 +627,18 @@ typedef struct { #define GIT_DIFF_FIND_OPTIONS_VERSION 1 #define GIT_DIFF_FIND_OPTIONS_INIT {GIT_DIFF_FIND_OPTIONS_VERSION} +/** + * Initializes a `git_diff_find_options` with default values. Equivalent to + * creating an instance with GIT_DIFF_FIND_OPTIONS_INIT. + * + * @param opts The `git_diff_find_options` struct to initialize + * @param version Version of struct; pass `GIT_DIFF_FIND_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_diff_find_init_options( + git_diff_find_options *opts, + unsigned int version); + /** @name Diff Generator Functions * * These are the functions you would use to create (or destroy) a @@ -662,24 +734,17 @@ GIT_EXTERN(int) git_diff_index_to_workdir( * The tree you provide will be used for the "old_file" side of the delta, * and the working directory will be used for the "new_file" side. * - * Please note: this is *NOT* the same as `git diff <treeish>`. Running - * `git diff HEAD` or the like actually uses information from the index, - * along with the tree and working directory info. + * This is not the same as `git diff <treeish>` or `git diff-index + * <treeish>`. Those commands use information from the index, whereas this + * function strictly returns the differences between the tree and the files + * in the working directory, regardless of the state of the index. Use + * `git_diff_tree_to_workdir_with_index` to emulate those commands. * - * This function returns strictly the differences between the tree and the - * files contained in the working directory, regardless of the state of - * files in the index. It may come as a surprise, but there is no direct - * equivalent in core git. - * - * To emulate `git diff <tree>`, use `git_diff_tree_to_workdir_with_index` - * (or `git_diff_tree_to_index` and `git_diff_index_to_workdir`, then call - * `git_diff_merge` on the results). That will yield a `git_diff` that - * matches the git output. - * - * If this seems confusing, take the case of a file with a staged deletion - * where the file has then been put back into the working dir and modified. - * The tree-to-workdir diff for that file is 'modified', but core git would - * show status 'deleted' since there is a pending deletion in the index. + * To see difference between this and `git_diff_tree_to_workdir_with_index`, + * consider the example of a staged file deletion where the file has then + * been put back into the working dir and further modified. The + * tree-to-workdir diff for that file is 'modified', but `git diff` would + * show status 'deleted' since there is a staged delete. * * @param diff A pointer to a git_diff pointer that will be allocated. * @param repo The repository containing the tree. @@ -744,23 +809,6 @@ GIT_EXTERN(int) git_diff_find_similar( git_diff *diff, const git_diff_find_options *options); -/** - * Initialize diff options structure - * - * In most cases, you can probably just use `GIT_DIFF_OPTIONS_INIT` to - * initialize the diff options structure, but in some cases that is not - * going to work. You can call this function instead. Note that you - * must pass both a pointer to the structure to be initialized and the - * `GIT_DIFF_OPTIONS_VERSION` value from the header you compiled with. - * - * @param options Pointer to git_diff_options memory to be initialized - * @param version Should be `GIT_DIFF_OPTIONS_VERSION` - * @return 0 on success, negative on failure (such as unsupported version) - */ -GIT_EXTERN(int) git_diff_options_init( - git_diff_options *options, - unsigned int version); - /**@}*/ @@ -833,7 +881,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. @@ -844,7 +892,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, @@ -881,13 +929,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, @@ -927,7 +975,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, @@ -962,7 +1010,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, @@ -976,6 +1024,214 @@ GIT_EXTERN(int) git_diff_blob_to_buffer( git_diff_line_cb line_cb, void *payload); +/** + * Directly run a diff between two buffers. + * + * Even more than with `git_diff_blobs`, comparing two buffer lacks + * context, so the `git_diff_file` parameters to the callbacks will be + * faked a la the rules for `git_diff_blobs()`. + * + * @param old_buffer Raw data for old side of diff, or NULL for empty + * @param old_len Length of the raw data for old side of the diff + * @param old_as_path Treat old buffer as if it had this filename; can be NULL + * @param new_buffer Raw data for new side of diff, or NULL for empty + * @param new_len Length of raw data for new side of diff + * @param new_as_path Treat buffer as if it had this filename; can be NULL + * @param options Options for diff, or NULL for default options + * @param file_cb Callback for "file"; made once if there is a diff; can be NULL + * @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, non-zero callback return value, or error code + */ +GIT_EXTERN(int) git_diff_buffers( + const void *old_buffer, + size_t old_len, + const char *old_as_path, + const void *new_buffer, + size_t new_len, + const char *new_as_path, + const git_diff_options *options, + git_diff_file_cb file_cb, + git_diff_hunk_cb hunk_cb, + git_diff_line_cb line_cb, + void *payload); + +/** + * This is an opaque structure which is allocated by `git_diff_get_stats`. + * You are responsible for releasing the object memory when done, using the + * `git_diff_stats_free()` function. + */ +typedef struct git_diff_stats git_diff_stats; + +/** + * Formatting options for diff stats + */ +typedef enum { + /** No stats*/ + GIT_DIFF_STATS_NONE = 0, + + /** Full statistics, equivalent of `--stat` */ + GIT_DIFF_STATS_FULL = (1u << 0), + + /** Short statistics, equivalent of `--shortstat` */ + GIT_DIFF_STATS_SHORT = (1u << 1), + + /** Number statistics, equivalent of `--numstat` */ + GIT_DIFF_STATS_NUMBER = (1u << 2), + + /** Extended header information such as creations, renames and mode changes, equivalent of `--summary` */ + GIT_DIFF_STATS_INCLUDE_SUMMARY = (1u << 3), +} git_diff_stats_format_t; + +/** + * Accumlate diff statistics for all patches. + * + * @param out Structure containg the diff statistics. + * @param diff A git_diff generated by one of the above functions. + * @return 0 on success; non-zero on error + */ +GIT_EXTERN(int) git_diff_get_stats( + git_diff_stats **out, + git_diff *diff); + +/** + * Get the total number of files changed in a diff + * + * @param stats A `git_diff_stats` generated by one of the above functions. + * @return total number of files changed in the diff + */ +GIT_EXTERN(size_t) git_diff_stats_files_changed( + const git_diff_stats *stats); + +/** + * Get the total number of insertions in a diff + * + * @param stats A `git_diff_stats` generated by one of the above functions. + * @return total number of insertions in the diff + */ +GIT_EXTERN(size_t) git_diff_stats_insertions( + const git_diff_stats *stats); + +/** + * Get the total number of deletions in a diff + * + * @param stats A `git_diff_stats` generated by one of the above functions. + * @return total number of deletions in the diff + */ +GIT_EXTERN(size_t) git_diff_stats_deletions( + const git_diff_stats *stats); + +/** + * Print diff statistics to a `git_buf`. + * + * @param out buffer to store the formatted diff statistics in. + * @param stats A `git_diff_stats` generated by one of the above functions. + * @param format Formatting option. + * @param width Target width for output (only affects GIT_DIFF_STATS_FULL) + * @return 0 on success; non-zero on error + */ +GIT_EXTERN(int) git_diff_stats_to_buf( + git_buf *out, + const git_diff_stats *stats, + git_diff_stats_format_t format, + size_t width); + +/** + * Deallocate a `git_diff_stats`. + * + * @param stats The previously created statistics object; + * cannot be used after free. + */ +GIT_EXTERN(void) git_diff_stats_free(git_diff_stats *stats); + +/** + * Formatting options for diff e-mail generation + */ +typedef enum { + /** Normal patch, the default */ + GIT_DIFF_FORMAT_EMAIL_NONE = 0, + + /** Don't insert "[PATCH]" in the subject header*/ + GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = (1 << 0), + +} git_diff_format_email_flags_t; + +/** + * Options for controlling the formatting of the generated e-mail. + */ +typedef struct { + unsigned int version; + + git_diff_format_email_flags_t flags; + + /** This patch number */ + size_t patch_no; + + /** Total number of patches in this series */ + size_t total_patches; + + /** id to use for the commit */ + const git_oid *id; + + /** Summary of the change */ + const char *summary; + + /** Author of the change */ + const git_signature *author; +} git_diff_format_email_options; + +#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1 +#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL} + +/** + * Create an e-mail ready patch from a diff. + * + * @param out buffer to store the e-mail patch in + * @param diff containing the commit + * @param opts structure with options to influence content and formatting. + * @return 0 or an error code + */ +GIT_EXTERN(int) git_diff_format_email( + git_buf *out, + git_diff *diff, + const git_diff_format_email_options *opts); + +/** + * Create an e-mail ready patch for a commit. + * + * Does not support creating patches for merge commits (yet). + * + * @param out buffer to store the e-mail patch in + * @param repo containing the commit + * @param commit pointer to up commit + * @param patch_no patch number of the commit + * @param total_patches total number of patches in the patch set + * @param flags determines the formatting of the e-mail + * @param diff_opts structure with options to influence diff or NULL for defaults. + * @return 0 or an error code + */ +GIT_EXTERN(int) git_diff_commit_as_email( + git_buf *out, + git_repository *repo, + git_commit *commit, + size_t patch_no, + size_t total_patches, + git_diff_format_email_flags_t flags, + const git_diff_options *diff_opts); + +/** + * Initializes a `git_diff_format_email_options` with default values. + * + * Equivalent to creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT. + * + * @param opts The `git_diff_format_email_options` struct to initialize + * @param version Version of struct; pass `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_diff_format_email_init_options( + git_diff_format_email_options *opts, + unsigned int version); GIT_END_DECL diff --git a/include/git2/errors.h b/include/git2/errors.h index be7a31d8e..c914653fc 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -8,7 +8,6 @@ #define INCLUDE_git_errors_h__ #include "common.h" -#include "buffer.h" /** * @file git2/errors.h @@ -20,25 +19,39 @@ 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_EMODIFIED = -15, /**< Reference value does not match expected */ + + 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; @@ -71,6 +84,9 @@ typedef enum { GITERR_MERGE, GITERR_SSH, GITERR_FILTER, + GITERR_REVERT, + GITERR_CALLBACK, + GITERR_CHERRYPICK, } git_error_t; /** @@ -90,7 +106,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 diff --git a/include/git2/filter.h b/include/git2/filter.h index f96b6766b..e57a67e73 100644 --- a/include/git2/filter.h +++ b/include/git2/filter.h @@ -35,6 +35,11 @@ typedef enum { GIT_FILTER_CLEAN = GIT_FILTER_TO_ODB, } git_filter_mode_t; +typedef enum { + GIT_FILTER_OPT_DEFAULT = 0u, + GIT_FILTER_OPT_ALLOW_UNSAFE = (1u << 0), +} git_filter_opt_t; + /** * A filter that can transform file data * @@ -75,6 +80,7 @@ typedef struct git_filter_list git_filter_list; * @param blob The blob to which the filter will be applied (if known) * @param path Relative path of the file to be filtered * @param mode Filtering direction (WT->ODB or ODB->WT) + * @param options Combination of `git_filter_opt_t` flags * @return 0 on success (which could still return NULL if no filters are * needed for the requested file), <0 on error */ @@ -83,7 +89,8 @@ GIT_EXTERN(int) git_filter_list_load( git_repository *repo, git_blob *blob, /* can be NULL */ const char *path, - git_filter_mode_t mode); + git_filter_mode_t mode, + uint32_t options); /** * Apply filter list to a data buffer. diff --git a/include/git2/graph.h b/include/git2/graph.h index a2710219e..c997d8ca9 100644 --- a/include/git2/graph.h +++ b/include/git2/graph.h @@ -36,6 +36,20 @@ GIT_BEGIN_DECL */ GIT_EXTERN(int) git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *local, const git_oid *upstream); + +/** + * Determine if a commit is the descendant of another commit. + * + * @param commit a previously loaded commit. + * @param ancestor a potential ancestor commit. + * @return 1 if the given commit is a descendant of the potential ancestor, + * 0 if not, error code otherwise. + */ +GIT_EXTERN(int) git_graph_descendant_of( + git_repository *repo, + const git_oid *commit, + const git_oid *ancestor); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/index.h b/include/git2/index.h index a60db370a..0b4476b4e 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -56,12 +56,12 @@ typedef struct git_index_entry { unsigned int gid; git_off_t file_size; - git_oid oid; + git_oid id; unsigned short flags; unsigned short flags_extended; - char *path; + const char *path; } git_index_entry; /** @@ -73,11 +73,19 @@ typedef struct git_index_entry { */ #define GIT_IDXENTRY_NAMEMASK (0x0fff) #define GIT_IDXENTRY_STAGEMASK (0x3000) -#define GIT_IDXENTRY_EXTENDED (0x4000) -#define GIT_IDXENTRY_VALID (0x8000) #define GIT_IDXENTRY_STAGESHIFT 12 -#define GIT_IDXENTRY_STAGE(E) (((E)->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT) +typedef enum { + GIT_IDXENTRY_EXTENDED = (0x4000), + GIT_IDXENTRY_VALID = (0x8000), +} git_indxentry_flag_t; + +#define GIT_IDXENTRY_STAGE(E) \ + (((E)->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT) + +#define GIT_IDXENTRY_STAGE_SET(E,S) do { \ + (E)->flags = ((E)->flags & ~GIT_IDXENTRY_STAGEMASK) | \ + (((S) & 0x03) << GIT_IDXENTRY_STAGESHIFT); } while (0) /** * Bitmasks for on-disk fields of `git_index_entry`'s `flags_extended` @@ -87,43 +95,43 @@ typedef struct git_index_entry { * in-memory only and used by libgit2. Only the flags in * `GIT_IDXENTRY_EXTENDED_FLAGS` will get saved on-disk. * - * These bitmasks match the three fields in the `git_index_entry` - * `flags_extended` value that belong on disk. You can use them to - * interpret the data in the `flags_extended`. + * Thee first three bitmasks match the three fields in the + * `git_index_entry` `flags_extended` value that belong on disk. You + * can use them to interpret the data in the `flags_extended`. + * + * The rest of the bitmasks match the other fields in the `git_index_entry` + * `flags_extended` value that are only used in-memory by libgit2. + * You can use them to interpret the data in the `flags_extended`. + * */ -#define GIT_IDXENTRY_INTENT_TO_ADD (1 << 13) -#define GIT_IDXENTRY_SKIP_WORKTREE (1 << 14) -/* GIT_IDXENTRY_EXTENDED2 is reserved for future extension */ -#define GIT_IDXENTRY_EXTENDED2 (1 << 15) +typedef enum { -#define GIT_IDXENTRY_EXTENDED_FLAGS (GIT_IDXENTRY_INTENT_TO_ADD | GIT_IDXENTRY_SKIP_WORKTREE) + GIT_IDXENTRY_INTENT_TO_ADD = (1 << 13), + GIT_IDXENTRY_SKIP_WORKTREE = (1 << 14), + /** Reserved for future extension */ + GIT_IDXENTRY_EXTENDED2 = (1 << 15), -/** - * Bitmasks for in-memory only fields of `git_index_entry`'s `flags_extended` - * - * These bitmasks match the other fields in the `git_index_entry` - * `flags_extended` value that are only used in-memory by libgit2. You - * can use them to interpret the data in the `flags_extended`. - */ -#define GIT_IDXENTRY_UPDATE (1 << 0) -#define GIT_IDXENTRY_REMOVE (1 << 1) -#define GIT_IDXENTRY_UPTODATE (1 << 2) -#define GIT_IDXENTRY_ADDED (1 << 3) + GIT_IDXENTRY_EXTENDED_FLAGS = (GIT_IDXENTRY_INTENT_TO_ADD | GIT_IDXENTRY_SKIP_WORKTREE), + GIT_IDXENTRY_UPDATE = (1 << 0), + GIT_IDXENTRY_REMOVE = (1 << 1), + GIT_IDXENTRY_UPTODATE = (1 << 2), + GIT_IDXENTRY_ADDED = (1 << 3), -#define GIT_IDXENTRY_HASHED (1 << 4) -#define GIT_IDXENTRY_UNHASHED (1 << 5) -#define GIT_IDXENTRY_WT_REMOVE (1 << 6) /* remove in work directory */ -#define GIT_IDXENTRY_CONFLICTED (1 << 7) + GIT_IDXENTRY_HASHED = (1 << 4), + GIT_IDXENTRY_UNHASHED = (1 << 5), + GIT_IDXENTRY_WT_REMOVE = (1 << 6), /**< remove in work directory */ + GIT_IDXENTRY_CONFLICTED = (1 << 7), -#define GIT_IDXENTRY_UNPACKED (1 << 8) -#define GIT_IDXENTRY_NEW_SKIP_WORKTREE (1 << 9) + GIT_IDXENTRY_UNPACKED = (1 << 8), + GIT_IDXENTRY_NEW_SKIP_WORKTREE = (1 << 9), +} git_idxentry_extended_flag_t; /** Capabilities of system that affect index actions. */ typedef enum { - GIT_INDEXCAP_IGNORE_CASE = 1u, - GIT_INDEXCAP_NO_FILEMODE = 2u, - GIT_INDEXCAP_NO_SYMLINKS = 4u, - GIT_INDEXCAP_FROM_OWNER = ~0u + GIT_INDEXCAP_IGNORE_CASE = 1, + GIT_INDEXCAP_NO_FILEMODE = 2, + GIT_INDEXCAP_NO_SYMLINKS = 4, + GIT_INDEXCAP_FROM_OWNER = -1, } git_indexcap_t; /** Callback for APIs that add/remove/update files matching pathspec */ @@ -158,8 +166,8 @@ typedef enum { * to back it. * * Since there is no ODB or working directory behind this index, - * any Index methods which rely on these (e.g. index_add) will - * fail with the GIT_EBAREINDEX error code. + * any Index methods which rely on these (e.g. index_add_bypath) + * will fail with the GIT_ERROR error code. * * If you need to access the index of an actual repository, * use the `git_repository_index` wrapper. @@ -206,7 +214,7 @@ GIT_EXTERN(git_repository *) git_index_owner(const git_index *index); * @param index An existing index object * @return A combination of GIT_INDEXCAP values */ -GIT_EXTERN(unsigned int) git_index_caps(const git_index *index); +GIT_EXTERN(int) git_index_caps(const git_index *index); /** * Set index capabilities flags. @@ -219,7 +227,7 @@ GIT_EXTERN(unsigned int) git_index_caps(const git_index *index); * @param caps A combination of GIT_INDEXCAP values * @return 0 on success, -1 on failure */ -GIT_EXTERN(int) git_index_set_caps(git_index *index, unsigned int caps); +GIT_EXTERN(int) git_index_set_caps(git_index *index, int caps); /** * Update the contents of an existing index object in memory by reading @@ -255,7 +263,7 @@ GIT_EXTERN(int) git_index_write(git_index *index); * @param index an existing index object * @return path to index file or NULL for in-memory index */ -GIT_EXTERN(const char *) git_index_path(git_index *index); +GIT_EXTERN(const char *) git_index_path(const git_index *index); /** * Read a tree into the index file with stats @@ -327,12 +335,14 @@ GIT_EXTERN(size_t) git_index_entrycount(const git_index *index); /** * Clear the contents (all the entries) of an index object. - * This clears the index object in memory; changes must be manually - * written to disk for them to take effect. + * + * This clears the index object in memory; changes must be explicitly + * written to disk for them to take effect persistently. * * @param index an existing index object + * @return 0 on success, error code < 0 on failure */ -GIT_EXTERN(void) git_index_clear(git_index *index); +GIT_EXTERN(int) git_index_clear(git_index *index); /** * Get a pointer to one of the entries in the index @@ -405,10 +415,10 @@ GIT_EXTERN(int) git_index_add(git_index *index, const git_index_entry *source_en * * This entry is calculated from the entry's flag attribute like this: * - * (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT + * (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT * * @param entry The entry - * @returns the stage number + * @return the stage number */ GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry); @@ -493,7 +503,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 +512,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 +534,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 +563,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, @@ -568,8 +578,7 @@ GIT_EXTERN(int) git_index_update_all( * @param at_pos the address to which the position of the index entry is written (optional) * @param index an existing index object * @param path path to search - * @return a zero-based position in the index if found; - * GIT_ENOTFOUND otherwise + * @return a zero-based position in the index if found; GIT_ENOTFOUND otherwise */ GIT_EXTERN(int) git_index_find(size_t *at_pos, git_index *index, const char *path); @@ -613,6 +622,7 @@ GIT_EXTERN(int) git_index_conflict_add( * @param their_out Pointer to store the their entry * @param index an existing index object * @param path path to search + * @return 0 or an error code */ GIT_EXTERN(int) git_index_conflict_get( const git_index_entry **ancestor_out, @@ -625,16 +635,18 @@ GIT_EXTERN(int) git_index_conflict_get( * Removes the index entries that represent a conflict of a single file. * * @param index an existing index object - * @param path to search + * @param path path to remove conflicts for + * @return 0 or an error code */ GIT_EXTERN(int) git_index_conflict_remove(git_index *index, const char *path); /** - * Remove all conflicts in the index (entries with a stage greater than 0.) + * Remove all conflicts in the index (entries with a stage greater than 0). * * @param index an existing index object + * @return 0 or an error code */ -GIT_EXTERN(void) git_index_conflict_cleanup(git_index *index); +GIT_EXTERN(int) git_index_conflict_cleanup(git_index *index); /** * Determine if the index contains entries representing file conflicts. @@ -644,9 +656,12 @@ GIT_EXTERN(void) git_index_conflict_cleanup(git_index *index); GIT_EXTERN(int) git_index_has_conflicts(const git_index *index); /** - * Create an iterator for the conflicts in the index. You may not modify the - * index while iterating, the results are undefined. + * Create an iterator for the conflicts in the index. + * + * The index must not be modified while iterating; the results are undefined. * + * @param iterator_out The newly created conflict iterator + * @param index The index to scan * @return 0 or an error code */ GIT_EXTERN(int) git_index_conflict_iterator_new( diff --git a/include/git2/indexer.h b/include/git2/indexer.h index e4c03ad06..d2d315e47 100644 --- a/include/git2/indexer.h +++ b/include/git2/indexer.h @@ -32,7 +32,7 @@ GIT_EXTERN(int) git_indexer_new( const char *path, unsigned int mode, git_odb *odb, - git_transfer_progress_callback progress_cb, + git_transfer_progress_cb progress_cb, void *progress_cb_payload); /** diff --git a/include/git2/merge.h b/include/git2/merge.h index 3354fbeab..9eb14ccb1 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -23,70 +23,287 @@ GIT_BEGIN_DECL /** + * The file inputs to `git_merge_file`. Callers should populate the + * `git_merge_file_input` structure with descriptions of the files in + * each side of the conflict for use in producing the merge file. + */ +typedef struct { + unsigned int version; + + /** Pointer to the contents of the file. */ + const char *ptr; + + /** Size of the contents pointed to in `ptr`. */ + size_t size; + + /** File name of the conflicted file, or `NULL` to not merge the path. */ + const char *path; + + /** File mode of the conflicted file, or `0` to not merge the mode. */ + unsigned int mode; +} git_merge_file_input; + +#define GIT_MERGE_FILE_INPUT_VERSION 1 +#define GIT_MERGE_FILE_INPUT_INIT {GIT_MERGE_FILE_INPUT_VERSION} + +/** + * Initializes a `git_merge_file_input` with default values. Equivalent to + * creating an instance with GIT_MERGE_FILE_INPUT_INIT. + * + * @param opts the `git_merge_file_input` instance to initialize. + * @param version the version of the struct; you should pass + * `GIT_MERGE_FILE_INPUT_VERSION` here. + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_merge_file_init_input( + git_merge_file_input *opts, + unsigned int version); + +/** * Flags for `git_merge_tree` options. A combination of these flags can be - * passed in via the `flags` value in the `git_merge_tree_opts`. + * passed in via the `flags` value in the `git_merge_options`. */ typedef enum { - /** Detect renames */ + /** + * Detect renames that occur between the common ancestor and the "ours" + * side or the common ancestor and the "theirs" side. This will enable + * the ability to merge between a modified and renamed file. + */ GIT_MERGE_TREE_FIND_RENAMES = (1 << 0), } git_merge_tree_flag_t; /** - * Automerge options for `git_merge_trees_opts`. + * Merge file favor options for `git_merge_options` instruct the file-level + * merging functionality how to deal with conflicting regions of the files. */ typedef enum { - GIT_MERGE_AUTOMERGE_NORMAL = 0, - GIT_MERGE_AUTOMERGE_NONE = 1, - GIT_MERGE_AUTOMERGE_FAVOR_OURS = 2, - GIT_MERGE_AUTOMERGE_FAVOR_THEIRS = 3, -} git_merge_automerge_flags; + /** + * When a region of a file is changed in both branches, a conflict + * will be recorded in the index so that `git_checkout` can produce + * a merge file with conflict markers in the working directory. + * This is the default. + */ + GIT_MERGE_FILE_FAVOR_NORMAL = 0, + /** + * When a region of a file is changed in both branches, the file + * created in the index will contain the "ours" side of any conflicting + * region. The index will not record a conflict. + */ + GIT_MERGE_FILE_FAVOR_OURS = 1, + + /** + * When a region of a file is changed in both branches, the file + * created in the index will contain the "theirs" side of any conflicting + * region. The index will not record a conflict. + */ + GIT_MERGE_FILE_FAVOR_THEIRS = 2, + + /** + * When a region of a file is changed in both branches, the file + * created in the index will contain each unique line from each side, + * which has the result of combining both files. The index will not + * record a conflict. + */ + GIT_MERGE_FILE_FAVOR_UNION = 3, +} git_merge_file_favor_t; + +typedef enum { + /* Defaults */ + GIT_MERGE_FILE_DEFAULT = 0, + + /* Create standard conflicted merge files */ + GIT_MERGE_FILE_STYLE_MERGE = (1 << 0), + + /* Create diff3-style files */ + GIT_MERGE_FILE_STYLE_DIFF3 = (1 << 1), + + /* Condense non-alphanumeric regions for simplified diff file */ + GIT_MERGE_FILE_SIMPLIFY_ALNUM = (1 << 2), +} git_merge_file_flags_t; + +typedef struct { + unsigned int version; + + /** + * Label for the ancestor file side of the conflict which will be prepended + * to labels in diff3-format merge files. + */ + const char *ancestor_label; + + /** + * Label for our file side of the conflict which will be prepended + * to labels in merge files. + */ + const char *our_label; + + /** + * Label for their file side of the conflict which will be prepended + * to labels in merge files. + */ + const char *their_label; + + /** The file to favor in region conflicts. */ + git_merge_file_favor_t favor; + + /** Merge file flags. */ + git_merge_file_flags_t flags; +} git_merge_file_options; + +#define GIT_MERGE_FILE_OPTIONS_VERSION 1 +#define GIT_MERGE_FILE_OPTIONS_INIT {GIT_MERGE_FILE_OPTIONS_VERSION} + +/** + * Initializes a `git_merge_file_options` with default values. Equivalent to + * creating an instance with GIT_MERGE_FILE_OPTIONS_INIT. + * + * @param opts the `git_merge_file_options` instance to initialize. + * @param version the version of the struct; you should pass + * `GIT_MERGE_FILE_OPTIONS_VERSION` here. + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_merge_file_init_options( + git_merge_file_options *opts, + unsigned int version); + +typedef struct { + /** + * True if the output was automerged, false if the output contains + * conflict markers. + */ + unsigned int automergeable; + + /** + * The path that the resultant merge file should use, or NULL if a + * filename conflict would occur. + */ + const char *path; + + /** The mode that the resultant merge file should use. */ + unsigned int mode; + + /** The contents of the merge. */ + const char *ptr; + + /** The length of the merge contents. */ + size_t len; +} git_merge_file_result; typedef struct { unsigned int version; git_merge_tree_flag_t flags; - /** Similarity to consider a file renamed (default 50) */ + /** + * Similarity to consider a file renamed (default 50). If + * `GIT_MERGE_TREE_FIND_RENAMES` is enabled, added files will be compared + * with deleted files to determine their similarity. Files that are + * more similar than the rename threshold (percentage-wise) will be + * treated as a rename. + */ unsigned int rename_threshold; - /** Maximum similarity sources to examine (overrides the - * `merge.renameLimit` config) (default 200) + /** + * Maximum similarity sources to examine for renames (default 200). + * If the number of rename candidates (add / delete pairs) is greater + * than this value, inexact rename detection is aborted. + * + * This setting overrides the `merge.renameLimit` configuration value. */ unsigned int target_limit; /** Pluggable similarity metric; pass NULL to use internal metric */ git_diff_similarity_metric *metric; - /** Flags for automerging content. */ - git_merge_automerge_flags automerge_flags; -} git_merge_tree_opts; - -#define GIT_MERGE_TREE_OPTS_VERSION 1 -#define GIT_MERGE_TREE_OPTS_INIT {GIT_MERGE_TREE_OPTS_VERSION} + /** Flags for handling conflicting content. */ + git_merge_file_favor_t file_favor; +} git_merge_options; +#define GIT_MERGE_OPTIONS_VERSION 1 +#define GIT_MERGE_OPTIONS_INIT {GIT_MERGE_OPTIONS_VERSION} /** - * Option flags for `git_merge`. + * Initializes a `git_merge_options` with default values. Equivalent to + * creating an instance with GIT_MERGE_OPTIONS_INIT. * - * GIT_MERGE_NO_FASTFORWARD - Do not fast-forward. + * @param opts the `git_merge_options` instance to initialize. + * @param version the version of the struct; you should pass + * `GIT_MERGE_OPTIONS_VERSION` here. + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_merge_init_options( + git_merge_options *opts, + unsigned int version); + +/** + * The results of `git_merge_analysis` indicate the merge opportunities. */ typedef enum { - GIT_MERGE_NO_FASTFORWARD = 1, - GIT_MERGE_FASTFORWARD_ONLY = 2, -} git_merge_flags_t; + /** No merge is possible. (Unused.) */ + GIT_MERGE_ANALYSIS_NONE = 0, -typedef struct { - unsigned int version; + /** + * A "normal" merge; both HEAD and the given merge input have diverged + * from their common ancestor. The divergent commits must be merged. + */ + GIT_MERGE_ANALYSIS_NORMAL = (1 << 0), + + /** + * All given merge inputs are reachable from HEAD, meaning the + * repository is up-to-date and no merge needs to be performed. + */ + GIT_MERGE_ANALYSIS_UP_TO_DATE = (1 << 1), + + /** + * The given merge input is a fast-forward from HEAD and no merge + * needs to be performed. Instead, the client can check out the + * given merge input. + */ + GIT_MERGE_ANALYSIS_FASTFORWARD = (1 << 2), + + /** + * The HEAD of the current repository is "unborn" and does not point to + * a valid commit. No merge can be performed, but the caller may wish + * to simply set HEAD to the target commit(s). + */ + GIT_MERGE_ANALYSIS_UNBORN = (1 << 3), +} git_merge_analysis_t; - git_merge_flags_t merge_flags; - git_merge_tree_opts merge_tree_opts; +typedef enum { + /* + * No configuration was found that suggests a preferred behavior for + * merge. + */ + GIT_MERGE_PREFERENCE_NONE = 0, - git_checkout_opts checkout_opts; -} git_merge_opts; + /** + * There is a `merge.ff=false` configuration setting, suggesting that + * the user does not want to allow a fast-forward merge. + */ + GIT_MERGE_PREFERENCE_NO_FASTFORWARD = (1 << 0), -#define GIT_MERGE_OPTS_VERSION 1 -#define GIT_MERGE_OPTS_INIT {GIT_MERGE_OPTS_VERSION, 0, GIT_MERGE_TREE_OPTS_INIT, GIT_CHECKOUT_OPTS_INIT} + /** + * There is a `merge.ff=only` configuration setting, suggesting that + * the user only wants fast-forward merges. + */ + GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY = (1 << 1), +} git_merge_preference_t; +/** + * Analyzes the given branch(es) and determines the opportunities for + * merging them into the HEAD of the repository. + * + * @param analysis_out analysis enumeration that the result is written into + * @param repo the repository to merge + * @param their_heads the heads to merge into + * @param their_heads_len the number of heads to merge + * @return 0 on success or error code + */ +GIT_EXTERN(int) git_merge_analysis( + git_merge_analysis_t *analysis_out, + git_merge_preference_t *preference_out, + git_repository *repo, + const git_merge_head **their_heads, + size_t their_heads_len); /** * Find a merge base between two commits @@ -95,7 +312,7 @@ typedef struct { * @param repo the repository where the commits exist * @param one one of the commits * @param two the other commit - * @return Zero on success; GIT_ENOTFOUND or -1 on failure. + * @return 0 on success, GIT_ENOTFOUND if not found or error code */ GIT_EXTERN(int) git_merge_base( git_oid *out, @@ -119,27 +336,44 @@ GIT_EXTERN(int) git_merge_base_many( const git_oid input_array[]); /** - * Creates a `git_merge_head` from the given reference + * Find a merge base in preparation for an octopus merge + * + * @param out the OID of a merge base considering all the commits + * @param repo the repository where the commits exist + * @param length The number of commits in the provided `input_array` + * @param input_array oids of the commits + * @return Zero on success; GIT_ENOTFOUND or -1 on failure. + */ +GIT_EXTERN(int) git_merge_base_octopus( + git_oid *out, + git_repository *repo, + size_t length, + const git_oid input_array[]); + +/** + * Creates a `git_merge_head` from the given reference. The resulting + * git_merge_head must be freed with `git_merge_head_free`. * * @param out pointer to store the git_merge_head result in * @param repo repository that contains the given reference * @param ref reference to use as a merge input - * @return zero on success, -1 on failure. + * @return 0 on success or error code */ GIT_EXTERN(int) git_merge_head_from_ref( git_merge_head **out, git_repository *repo, - git_reference *ref); + const git_reference *ref); /** - * Creates a `git_merge_head` from the given fetch head data + * Creates a `git_merge_head` from the given fetch head data. The resulting + * git_merge_head must be freed with `git_merge_head_free`. * * @param out pointer to store the git_merge_head result in * @param repo repository that contains the given commit * @param branch_name name of the (remote) branch * @param remote_url url of the remote * @param oid the commit object id to use as a merge input - * @return zero on success, -1 on failure. + * @return 0 on success or error code */ GIT_EXTERN(int) git_merge_head_from_fetchhead( git_merge_head **out, @@ -149,20 +383,30 @@ GIT_EXTERN(int) git_merge_head_from_fetchhead( const git_oid *oid); /** - * Creates a `git_merge_head` from the given commit id + * Creates a `git_merge_head` from the given commit id. The resulting + * git_merge_head must be freed with `git_merge_head_free`. * * @param out pointer to store the git_merge_head result in * @param repo repository that contains the given commit - * @param oid the commit object id to use as a merge input - * @return zero on success, -1 on failure. + * @param id the commit object id to use as a merge input + * @return 0 on success or error code */ -GIT_EXTERN(int) git_merge_head_from_oid( +GIT_EXTERN(int) git_merge_head_from_id( git_merge_head **out, git_repository *repo, - const git_oid *oid); + const git_oid *id); /** - * Frees a `git_merge_head` + * Gets the commit ID that the given `git_merge_head` refers to. + * + * @param head the given merge head + * @return commit id + */ +GIT_EXTERN(const git_oid *) git_merge_head_id( + const git_merge_head *head); + +/** + * Frees a `git_merge_head`. * * @param head merge head to free */ @@ -170,8 +414,62 @@ GIT_EXTERN(void) git_merge_head_free( git_merge_head *head); /** + * Merge two files as they exist in the in-memory data structures, using + * the given common ancestor as the baseline, producing a + * `git_merge_file_result` that reflects the merge result. The + * `git_merge_file_result` must be freed with `git_merge_file_result_free`. + * + * Note that this function does not reference a repository and any + * configuration must be passed as `git_merge_file_options`. + * + * @param out The git_merge_file_result to be filled in + * @param ancestor The contents of the ancestor file + * @param ours The contents of the file in "our" side + * @param theirs The contents of the file in "their" side + * @param opts The merge file options or `NULL` for defaults + * @return 0 on success or error code + */ +GIT_EXTERN(int) git_merge_file( + git_merge_file_result *out, + const git_merge_file_input *ancestor, + const git_merge_file_input *ours, + const git_merge_file_input *theirs, + const git_merge_file_options *opts); + +/** + * Merge two files as they exist in the index, using the given common + * ancestor as the baseline, producing a `git_merge_file_result` that + * reflects the merge result. The `git_merge_file_result` must be freed with + * `git_merge_file_result_free`. + * + * @param out The git_merge_file_result to be filled in + * @param repo The repository + * @param ancestor The index entry for the ancestor file (stage level 1) + * @param ours The index entry for our file (stage level 2) + * @param theirs The index entry for their file (stage level 3) + * @param opts The merge file options or NULL + * @return 0 on success or error code + */ +GIT_EXTERN(int) git_merge_file_from_index( + git_merge_file_result *out, + git_repository *repo, + const git_index_entry *ancestor, + const git_index_entry *ours, + const git_index_entry *theirs, + const git_merge_file_options *opts); + +/** + * Frees a `git_merge_file_result`. + * + * @param result The result to free or `NULL` + */ +GIT_EXTERN(void) git_merge_file_result_free(git_merge_file_result *result); + +/** * Merge two trees, producing a `git_index` that reflects the result of - * the merge. + * the merge. The index may be written as-is to the working directory + * or checked out. If the index is to be converted to a tree, the caller + * should resolve any conflicts that arose as part of the merge. * * The returned index must be freed explicitly with `git_index_free`. * @@ -181,7 +479,7 @@ GIT_EXTERN(void) git_merge_head_free( * @param our_tree the tree that reflects the destination tree * @param their_tree the tree to merge in to `our_tree` * @param opts the merge tree options (or null for defaults) - * @return zero on success, -1 on failure. + * @return 0 on success or error code */ GIT_EXTERN(int) git_merge_trees( git_index **out, @@ -189,44 +487,49 @@ GIT_EXTERN(int) git_merge_trees( const git_tree *ancestor_tree, const git_tree *our_tree, const git_tree *their_tree, - const git_merge_tree_opts *opts); + const git_merge_options *opts); /** - * Merges the given commits into HEAD, producing a new commit. + * Merge two commits, producing a `git_index` that reflects the result of + * the merge. The index may be written as-is to the working directory + * or checked out. If the index is to be converted to a tree, the caller + * should resolve any conflicts that arose as part of the merge. * - * @param out the results of the merge - * @param repo the repository to merge - * @param merge_heads the heads to merge into - * @param merge_heads_len the number of heads to merge - * @param flags merge flags + * The returned index must be freed explicitly with `git_index_free`. + * + * @param out pointer to store the index result in + * @param repo repository that contains the given trees + * @param our_commit the commit that reflects the destination tree + * @param their_commit the commit to merge in to `our_commit` + * @param opts the merge tree options (or null for defaults) + * @return 0 on success or error code */ -GIT_EXTERN(int) git_merge( - git_merge_result **out, +GIT_EXTERN(int) git_merge_commits( + git_index **out, git_repository *repo, - const git_merge_head **their_heads, - size_t their_heads_len, - const git_merge_opts *opts); - -/** - * Returns true if a merge is up-to-date (we were asked to merge the target - * into itself.) - */ -GIT_EXTERN(int) git_merge_result_is_uptodate(git_merge_result *merge_result); - -/** - * Returns true if a merge is eligible for fastforward - */ -GIT_EXTERN(int) git_merge_result_is_fastforward(git_merge_result *merge_result); + const git_commit *our_commit, + const git_commit *their_commit, + const git_merge_options *opts); /** - * Gets the fast-forward OID if the merge was a fastforward. + * Merges the given commit(s) into HEAD, writing the results into the working + * directory. Any changes are staged for commit and any conflicts are written + * to the index. Callers should inspect the repository's index after this + * completes, resolve any conflicts and prepare a commit. * - * @param out the OID of the fast-forward - * @param merge_result the results of the merge + * @param repo the repository to merge + * @param their_heads the heads to merge into + * @param their_heads_len the number of heads to merge + * @param merge_opts merge options + * @param checkout_opts checkout options + * @return 0 on success or error code */ -GIT_EXTERN(int) git_merge_result_fastforward_oid(git_oid *out, git_merge_result *merge_result); - -GIT_EXTERN(void) git_merge_result_free(git_merge_result *merge_result); +GIT_EXTERN(int) git_merge( + git_repository *repo, + const git_merge_head **their_heads, + size_t their_heads_len, + const git_merge_options *merge_opts, + const git_checkout_options *checkout_opts); /** @} */ GIT_END_DECL diff --git a/include/git2/message.h b/include/git2/message.h index 395c88690..d78b1dce5 100644 --- a/include/git2/message.h +++ b/include/git2/message.h @@ -8,6 +8,7 @@ #define INCLUDE_git_message_h__ #include "common.h" +#include "buffer.h" /** * @file git2/message.h @@ -23,25 +24,19 @@ GIT_BEGIN_DECL * * Optionally, can remove lines starting with a "#". * - * @param out The user-allocated buffer which will be filled with the - * cleaned up message. Pass NULL if you just want to get the needed - * size of the prettified message as the output value. - * - * @param out_size Size of the `out` buffer in bytes. + * @param out The user-allocated git_buf which will be filled with the + * cleaned up message. * * @param message The message to be prettified. * - * @param strip_comments Non-zero to remove lines starting with "#", 0 to - * leave them in. + * @param strip_comments Non-zero to remove comment lines, 0 to leave them in. + * + * @param comment_char Comment character. Lines starting with this character + * are considered to be comments and removed if `strip_comments` is non-zero. * - * @return -1 on error, else number of characters in prettified message - * including the trailing NUL byte + * @return 0 or an error code. */ -GIT_EXTERN(int) git_message_prettify( - char *out, - size_t out_size, - const char *message, - int strip_comments); +GIT_EXTERN(int) git_message_prettify(git_buf *out, const char *message, int strip_comments, char comment_char); /** @} */ GIT_END_DECL diff --git a/include/git2/net.h b/include/git2/net.h index e70ba1f71..a727696a2 100644 --- a/include/git2/net.h +++ b/include/git2/net.h @@ -41,6 +41,11 @@ struct git_remote_head { git_oid oid; git_oid loid; char *name; + /** + * If the server send a symref mapping for this ref, this will + * point to the target. + */ + char *symref_target; }; /** diff --git a/include/git2/notes.h b/include/git2/notes.h index 76361633b..98eb2aef3 100644 --- a/include/git2/notes.h +++ b/include/git2/notes.h @@ -106,12 +106,12 @@ GIT_EXTERN(const char *) git_note_message(const git_note *note); /** - * Get the note object OID + * Get the note object's id * * @param note the note - * @return the note object OID + * @return the note object's id */ -GIT_EXTERN(const git_oid *) git_note_oid(const git_note *note); +GIT_EXTERN(const git_oid *) git_note_id(const git_note *note); /** * Add a note for an object @@ -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, diff --git a/include/git2/object.h b/include/git2/object.h index c40631fa6..9b13d824e 100644 --- a/include/git2/object.h +++ b/include/git2/object.h @@ -10,6 +10,7 @@ #include "common.h" #include "types.h" #include "oid.h" +#include "buffer.h" /** * @file git2/object.h @@ -104,6 +105,20 @@ GIT_EXTERN(int) git_object_lookup_bypath( GIT_EXTERN(const git_oid *) git_object_id(const git_object *obj); /** + * Get a short abbreviated OID string for the object + * + * This starts at the "core.abbrev" length (default 7 characters) and + * iteratively extends to a longer string if that length is ambiguous. + * The result will be unambiguous (at least until new objects are added to + * the repository). + * + * @param out Buffer to write string into + * @param obj The object to get an ID for + * @return 0 on success, <0 for error + */ +GIT_EXTERN(int) git_object_short_id(git_buf *out, const git_object *obj); + +/** * Get the object type of an object * * @param obj the repository object @@ -143,7 +158,7 @@ GIT_EXTERN(git_repository *) git_object_owner(const git_object *obj); GIT_EXTERN(void) git_object_free(git_object *object); /** - * Convert an object type to it's string representation. + * Convert an object type to its string representation. * * The result is a pointer to a string in static memory and * should not be free()'ed. diff --git a/include/git2/odb.h b/include/git2/odb.h index ad56384f0..114f6b317 100644 --- a/include/git2/odb.h +++ b/include/git2/odb.h @@ -159,6 +159,19 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_out, git_otype *type_out, git_od GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id); /** + * Determine if objects can be found in the object database from a short OID. + * + * @param out The full OID of the found object if just one is found. + * @param db The database to be searched for the given object. + * @param short_id A prefix of the id of the object to read. + * @param len The length of the prefix. + * @return 0 if found, GIT_ENOTFOUND if not found, GIT_EAMBIGUOUS if multiple + * matches were found, other value < 0 if there was a read error. + */ +GIT_EXTERN(int) git_odb_exists_prefix( + git_oid *out, git_odb *db, const git_oid *short_id, size_t len); + +/** * Refresh the object database to load newly added files. * * If the object databases have changed on disk while the library @@ -189,7 +202,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); @@ -325,7 +338,7 @@ GIT_EXTERN(int) git_odb_open_rstream(git_odb_stream **out, git_odb *db, const gi GIT_EXTERN(int) git_odb_write_pack( git_odb_writepack **out, git_odb *db, - git_transfer_progress_callback progress_cb, + git_transfer_progress_cb progress_cb, void *progress_payload); /** diff --git a/include/git2/oid.h b/include/git2/oid.h index 384b656d7..1cfd4e5e2 100644 --- a/include/git2/oid.h +++ b/include/git2/oid.h @@ -167,10 +167,7 @@ GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b); * @param b second oid structure. * @return true if equal, false otherwise */ -GIT_INLINE(int) git_oid_equal(const git_oid *a, const git_oid *b) -{ - return !git_oid_cmp(a, b); -} +GIT_EXTERN(int) git_oid_equal(const git_oid *a, const git_oid *b); /** * Compare the first 'len' hexadecimal characters (packets of 4 bits) diff --git a/include/git2/pack.h b/include/git2/pack.h index 88a2716bb..e7f060d12 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -52,7 +52,7 @@ typedef enum { GIT_PACKBUILDER_ADDING_OBJECTS = 0, GIT_PACKBUILDER_DELTAFICATION = 1, } git_packbuilder_stage_t; - + /** * Initialize a new packbuilder * @@ -115,6 +115,17 @@ GIT_EXTERN(int) git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid * GIT_EXTERN(int) git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid *id); /** + * Write the contents of the packfile to an in-memory buffer + * + * The contents of the buffer will become a valid packfile, even though there + * will be no attached index + * + * @param buf Buffer where to write the packfile + * @param pb The packbuilder + */ +GIT_EXTERN(int) git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb); + +/** * Write the new pack and corresponding index file to path. * * @param pb The packbuilder @@ -129,7 +140,7 @@ GIT_EXTERN(int) git_packbuilder_write( git_packbuilder *pb, const char *path, unsigned int mode, - git_transfer_progress_callback progress_cb, + git_transfer_progress_cb progress_cb, void *progress_cb_payload); /** @@ -143,6 +154,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 * diff --git a/include/git2/patch.h b/include/git2/patch.h index 6a6ad92d7..47c395669 100644 --- a/include/git2/patch.h +++ b/include/git2/patch.h @@ -106,6 +106,34 @@ GIT_EXTERN(int) git_patch_from_blob_and_buffer( const git_diff_options *opts); /** + * Directly generate a patch from the difference between two buffers. + * + * This is just like `git_diff_buffers()` except it generates a patch + * object for the difference instead of directly making callbacks. You can + * use the standard `git_patch` accessor functions to read the patch + * data, and you must call `git_patch_free()` on the patch when done. + * + * @param out The generated patch; NULL on error + * @param old_buffer Raw data for old side of diff, or NULL for empty + * @param old_len Length of the raw data for old side of the diff + * @param old_as_path Treat old buffer as if it had this filename; can be NULL + * @param new_buffer Raw data for new side of diff, or NULL for empty + * @param new_len Length of raw data for new side of diff + * @param new_as_path Treat buffer as if it had this filename; can be NULL + * @param opts Options for diff, or NULL for default options + * @return 0 on success or error code < 0 + */ +GIT_EXTERN(int) git_patch_from_buffers( + git_patch **out, + const void *old_buffer, + size_t old_len, + const char *old_as_path, + const char *new_buffer, + size_t new_len, + const char *new_as_path, + const git_diff_options *opts); + +/** * Free a git_patch object. */ GIT_EXTERN(void) git_patch_free(git_patch *patch); @@ -113,12 +141,12 @@ GIT_EXTERN(void) git_patch_free(git_patch *patch); /** * Get the delta associated with a patch */ -GIT_EXTERN(const git_diff_delta *) git_patch_get_delta(git_patch *patch); +GIT_EXTERN(const git_diff_delta *) git_patch_get_delta(const git_patch *patch); /** * Get the number of hunks in a patch */ -GIT_EXTERN(size_t) git_patch_num_hunks(git_patch *patch); +GIT_EXTERN(size_t) git_patch_num_hunks(const git_patch *patch); /** * Get line counts of each type in a patch. @@ -169,7 +197,7 @@ GIT_EXTERN(int) git_patch_get_hunk( * @return Number of lines in hunk or -1 if invalid hunk index */ GIT_EXTERN(int) git_patch_num_lines_in_hunk( - git_patch *patch, + const git_patch *patch, size_t hunk_idx); /** @@ -218,13 +246,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, @@ -234,15 +262,14 @@ GIT_EXTERN(int) git_patch_print( /** * Get the content of a patch as a single diff text. * - * @param string Allocated string; caller must free. + * @param out The git_buf to be filled in * @param patch A git_patch representing changes to one file * @return 0 on success, <0 on failure. */ -GIT_EXTERN(int) git_patch_to_str( - char **string, +GIT_EXTERN(int) git_patch_to_buf( + git_buf *out, git_patch *patch); - GIT_END_DECL /**@}*/ diff --git a/include/git2/pathspec.h b/include/git2/pathspec.h index 2fb0bb716..de6f027c5 100644 --- a/include/git2/pathspec.h +++ b/include/git2/pathspec.h @@ -12,6 +12,8 @@ #include "strarray.h" #include "diff.h" +GIT_BEGIN_DECL + /** * Compiled pathspec */ @@ -257,4 +259,5 @@ GIT_EXTERN(size_t) git_pathspec_match_list_failed_entrycount( GIT_EXTERN(const char *) git_pathspec_match_list_failed_entry( const git_pathspec_match_list *m, size_t pos); +GIT_END_DECL #endif diff --git a/include/git2/push.h b/include/git2/push.h index 77ef74039..cbf115661 100644 --- a/include/git2/push.h +++ b/include/git2/push.h @@ -39,6 +39,19 @@ typedef struct { #define GIT_PUSH_OPTIONS_VERSION 1 #define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION } +/** + * Initializes a `git_push_options` with default values. Equivalent to + * creating an instance with GIT_PUSH_OPTIONS_INIT. + * + * @param opts the `git_push_options` instance to initialize. + * @param version the version of the struct; you should pass + * `GIT_PUSH_OPTIONS_VERSION` here. + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_push_init_options( + git_push_options *opts, + unsigned int version); + /** Push network progress notification function */ typedef int (*git_push_transfer_progress)( unsigned int current, @@ -103,10 +116,16 @@ GIT_EXTERN(int) git_push_add_refspec(git_push *push, const char *refspec); * Update remote tips after a push * * @param push The push object + * @param signature The identity to use when updating reflogs + * @param reflog_message The message to insert into the reflogs. If NULL, the + * default is "update by push". * * @return 0 or an error code */ -GIT_EXTERN(int) git_push_update_tips(git_push *push); +GIT_EXTERN(int) git_push_update_tips( + git_push *push, + const git_signature *signature, + const char *reflog_message); /** * Actually push all given refspecs @@ -129,20 +148,22 @@ GIT_EXTERN(int) git_push_finish(git_push *push); * * @return true if remote side successfully unpacked, false otherwise */ -GIT_EXTERN(int) git_push_unpack_ok(git_push *push); +GIT_EXTERN(int) git_push_unpack_ok(const 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), diff --git a/include/git2/reflog.h b/include/git2/reflog.h index 2d1b6eeaa..ac42a231c 100644 --- a/include/git2/reflog.h +++ b/include/git2/reflog.h @@ -47,7 +47,7 @@ GIT_EXTERN(int) git_reflog_read(git_reflog **out, git_repository *repo, const c GIT_EXTERN(int) git_reflog_write(git_reflog *reflog); /** - * Add a new entry to the reflog. + * Add a new entry to the in-memory reflog. * * `msg` is optional and can be NULL. * @@ -60,23 +60,6 @@ GIT_EXTERN(int) git_reflog_write(git_reflog *reflog); GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *id, const git_signature *committer, const char *msg); /** - * Add a new entry to the named reflog. - * - * This utility function loads the named reflog, appends to it and - * writes it back out to the backend. - * - * `msg` is optional and can be NULL. - * - * @param repo the repository to act on - * @param name the reflog's name - * @param id the OID the reference is now pointing to - * @param committer the signature of the committer - * @param msg the reflog message - * @return 0 or an error code - */ -GIT_EXTERN(int) git_reflog_append_to(git_repository *repo, const char *name, const git_oid *id, const git_signature *committer, const char *msg); - -/** * Rename a reflog * * The reflog to be renamed is expected to already exist @@ -86,7 +69,7 @@ GIT_EXTERN(int) git_reflog_append_to(git_repository *repo, const char *name, con * * @param repo the repository * @param old_name the old name of the reference - * @param new_name the new name of the reference + * @param name the new name of the reference * @return 0 on success, GIT_EINVALIDSPEC or an error code */ GIT_EXTERN(int) git_reflog_rename(git_repository *repo, const char *old_name, const char *name); diff --git a/include/git2/refs.h b/include/git2/refs.h index 4041947f6..e5bb15c7c 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -27,7 +27,7 @@ GIT_BEGIN_DECL * The returned reference must be freed by the user. * * The name will be checked for validity. - * See `git_reference_create_symbolic()` for rules about valid names. + * See `git_reference_symbolic_create()` for rules about valid names. * * @param out pointer to the looked-up reference * @param repo the repository to look up the reference @@ -68,6 +68,48 @@ GIT_EXTERN(int) git_reference_name_to_id( GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, const char *shorthand); /** + * Conditionally create a new symbolic reference. + * + * A symbolic reference is a reference name that refers to another + * reference name. If the other name moves, the symbolic name will move, + * too. As a simple example, the "HEAD" reference might refer to + * "refs/heads/master" while on the "master" branch of a repository. + * + * The symbolic reference will be created in the repository and written to + * the disk. The generated reference object must be freed by the user. + * + * Valid reference names must follow one of two patterns: + * + * 1. Top-level names must contain only capital letters and underscores, + * and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD"). + * 2. Names prefixed with "refs/" can be almost anything. You must avoid + * the characters '~', '^', ':', '\\', '?', '[', and '*', and the + * sequences ".." and "@{" which have special meaning to revparse. + * + * This function will return an error if a reference already exists with the + * given name unless `force` is true, in which case it will be overwritten. + * + * The signature and message for the reflog will be ignored if the + * reference does not belong in the standard set (HEAD, branches and + * remote-tracking branches) and it does not have a reflog. + * + * It will return GIT_EMODIFIED if the reference's value at the time + * of updating does not match the one passed through `current_value` + * (i.e. if the ref has changed since the user read it). + * + * @param out Pointer to the newly created reference + * @param repo Repository where that reference will live + * @param name The name of the reference + * @param target The target of the reference + * @param force Overwrite existing references + * @param current_value The expected value of the reference when updating + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog + * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC, GIT_EMODIFIED or an error code + */ +GIT_EXTERN(int) git_reference_symbolic_create_matching(git_reference **out, git_repository *repo, const char *name, const char *target, int force, const char *current_value, const git_signature *signature, const char *log_message); + +/** * Create a new symbolic reference. * * A symbolic reference is a reference name that refers to another @@ -89,14 +131,20 @@ GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, co * This function will return an error if a reference already exists with the * given name unless `force` is true, in which case it will be overwritten. * + * The signature and message for the reflog will be ignored if the + * reference does not belong in the standard set (HEAD, branches and + * remote-tracking branches) and it does not have a reflog. + * * @param out Pointer to the newly created reference * @param repo Repository where that reference will live * @param name The name of the reference * @param target The target of the reference * @param force Overwrite existing references + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code */ -GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repository *repo, const char *name, const char *target, int force); +GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repository *repo, const char *name, const char *target, int force, const git_signature *signature, const char *log_message); /** * Create a new direct reference. @@ -121,14 +169,64 @@ GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repositor * This function will return an error if a reference already exists with the * given name unless `force` is true, in which case it will be overwritten. * + * The signature and message for the reflog will be ignored if the + * reference does not belong in the standard set (HEAD, branches and + * remote-tracking branches) and and it does not have a reflog. + * * @param out Pointer to the newly created reference * @param repo Repository where that reference will live * @param name The name of the reference * @param id The object id pointed to by the reference. * @param force Overwrite existing references + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code */ -GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force); +GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force, const git_signature *signature, const char *log_message); + +/** + * Conditionally create new direct reference + * + * A direct reference (also called an object id reference) refers directly + * to a specific object id (a.k.a. OID or SHA) in the repository. The id + * permanently refers to the object (although the reference itself can be + * moved). For example, in libgit2 the direct ref "refs/tags/v0.17.0" + * refers to OID 5b9fac39d8a76b9139667c26a63e6b3f204b3977. + * + * The direct reference will be created in the repository and written to + * the disk. The generated reference object must be freed by the user. + * + * Valid reference names must follow one of two patterns: + * + * 1. Top-level names must contain only capital letters and underscores, + * and must begin and end with a letter. (e.g. "HEAD", "ORIG_HEAD"). + * 2. Names prefixed with "refs/" can be almost anything. You must avoid + * the characters '~', '^', ':', '\\', '?', '[', and '*', and the + * sequences ".." and "@{" which have special meaning to revparse. + * + * This function will return an error if a reference already exists with the + * given name unless `force` is true, in which case it will be overwritten. + * + * The signature and message for the reflog will be ignored if the + * reference does not belong in the standard set (HEAD, branches and + * remote-tracking branches) and and it does not have a reflog. + * + * It will return GIT_EMODIFIED if the reference's value at the time + * of updating does not match the one passed through `current_id` + * (i.e. if the ref has changed since the user read it). + * + * @param out Pointer to the newly created reference + * @param repo Repository where that reference will live + * @param name The name of the reference + * @param id The object id pointed to by the reference. + * @param force Overwrite existing references + * @param current_id The expected value of the reference at the time of update + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog + * @return 0 on success, GIT_EMODIFIED if the value of the reference + * has changed, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code + */ +GIT_EXTERN(int) git_reference_create_matching(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force, const git_oid *current_id, const git_signature *signature, const char *log_message); /** * Get the OID pointed to by a direct reference. @@ -179,7 +277,7 @@ GIT_EXTERN(git_ref_t) git_reference_type(const git_reference *ref); /** * Get the full name of a reference. * - * See `git_reference_create_symbolic()` for rules about valid names. + * See `git_reference_symbolic_create()` for rules about valid names. * * @param ref The reference * @return the full name for the ref @@ -220,20 +318,28 @@ GIT_EXTERN(git_repository *) git_reference_owner(const git_reference *ref); * The new reference will be written to disk, overwriting the given reference. * * The target name will be checked for validity. - * See `git_reference_create_symbolic()` for rules about valid names. + * See `git_reference_symbolic_create()` for rules about valid names. + * + * The signature and message for the reflog will be ignored if the + * reference does not belong in the standard set (HEAD, branches and + * remote-tracking branches) and and it does not have a reflog. * * @param out Pointer to the newly created reference * @param ref The reference * @param target The new target for the reference + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog * @return 0 on success, GIT_EINVALIDSPEC or an error code */ GIT_EXTERN(int) git_reference_symbolic_set_target( git_reference **out, git_reference *ref, - const char *target); + const char *target, + const git_signature *signature, + const char *log_message); /** - * Create a new reference with the same name as the given reference but a + * Conditionally create a new reference with the same name as the given reference but a * different OID target. The reference must be a direct reference, otherwise * this will fail. * @@ -242,12 +348,17 @@ GIT_EXTERN(int) git_reference_symbolic_set_target( * @param out Pointer to the newly created reference * @param ref The reference * @param id The new target OID for the reference - * @return 0 or an error code + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog + * @return 0 on success, GIT_EMODIFIED if the value of the reference + * has changed since it was read, or an error code */ GIT_EXTERN(int) git_reference_set_target( git_reference **out, git_reference *ref, - const git_oid *id); + const git_oid *id, + const git_signature *signature, + const char *log_message); /** * Rename an existing reference. @@ -255,7 +366,7 @@ GIT_EXTERN(int) git_reference_set_target( * This method works for both direct and symbolic references. * * The new name will be checked for validity. - * See `git_reference_create_symbolic()` for rules about valid names. + * See `git_reference_symbolic_create()` for rules about valid names. * * If the `force` flag is not enabled, and there's already * a reference with the given name, the renaming will fail. @@ -268,6 +379,8 @@ GIT_EXTERN(int) git_reference_set_target( * @param ref The reference to rename * @param new_name The new name for the reference * @param force Overwrite an existing reference + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog * @return 0 on success, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code * */ @@ -275,7 +388,9 @@ GIT_EXTERN(int) git_reference_rename( git_reference **new_ref, git_reference *ref, const char *new_name, - int force); + int force, + const git_signature *signature, + const char *log_message); /** * Delete an existing reference. @@ -284,12 +399,26 @@ GIT_EXTERN(int) git_reference_rename( * will be immediately removed on disk but the memory will not be freed. * Callers must call `git_reference_free`. * + * This function will return an error if the reference has changed + * from the time it was looked up. + * * @param ref The reference to remove - * @return 0 or an error code + * @return 0, GIT_EMODIFIED or an error code */ GIT_EXTERN(int) git_reference_delete(git_reference *ref); /** + * Delete an existing reference by name + * + * This method removes the named reference from the repository without + * looking at its old value. + * + * @param name The reference to remove + * @return 0 or an error code + */ +GIT_EXTERN(int) git_reference_remove(git_repository *repo, const char *name); + +/** * Fill a list with all the references that can be found in a repository. * * The string array will be filled with the names of all references; these @@ -310,20 +439,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, @@ -343,7 +485,9 @@ GIT_EXTERN(void) git_reference_free(git_reference *ref); * @param ref2 The second git_reference * @return 0 if the same, else a stable but meaningless ordering. */ -GIT_EXTERN(int) git_reference_cmp(git_reference *ref1, git_reference *ref2); +GIT_EXTERN(int) git_reference_cmp( + const git_reference *ref1, + const git_reference *ref2); /** * Create an iterator for the repo's references @@ -379,6 +523,17 @@ GIT_EXTERN(int) git_reference_iterator_glob_new( */ GIT_EXTERN(int) git_reference_next(git_reference **out, git_reference_iterator *iter); +/** + * Get the next reference's name + * + * This function is provided for convenience in case only the names + * are interesting as it avoids the allocation of the `git_reference` + * object which `git_reference_next()` needs. + * + * @param out pointer in which to store the string + * @param iter the iterator + * @return 0, GIT_ITEROVER if there are no more; or an error code + */ GIT_EXTERN(int) git_reference_next_name(const char **out, git_reference_iterator *iter); /** @@ -415,12 +570,24 @@ GIT_EXTERN(int) git_reference_foreach_glob( /** * Check if a reflog exists for the specified reference. * - * @param ref A git reference - * + * @param repo the repository + * @param refname the reference's name * @return 0 when no reflog can be found, 1 when it exists; * otherwise an error code. */ -GIT_EXTERN(int) git_reference_has_log(git_reference *ref); +GIT_EXTERN(int) git_reference_has_log(git_repository *repo, const char *refname); + +/** + * Ensure there is a reflog for a particular reference. + * + * Make sure that successive updates to the reference will append to + * its log. + * + * @param repo the repository + * @param refname the reference's name + * @return 0 or an error code. + */ +GIT_EXTERN(int) git_reference_ensure_log(git_repository *repo, const char *refname); /** * Check if a reference is a local branch. @@ -430,7 +597,7 @@ GIT_EXTERN(int) git_reference_has_log(git_reference *ref); * @return 1 when the reference lives in the refs/heads * namespace; 0 otherwise. */ -GIT_EXTERN(int) git_reference_is_branch(git_reference *ref); +GIT_EXTERN(int) git_reference_is_branch(const git_reference *ref); /** * Check if a reference is a remote tracking branch @@ -440,7 +607,7 @@ GIT_EXTERN(int) git_reference_is_branch(git_reference *ref); * @return 1 when the reference lives in the refs/remotes * namespace; 0 otherwise. */ -GIT_EXTERN(int) git_reference_is_remote(git_reference *ref); +GIT_EXTERN(int) git_reference_is_remote(const git_reference *ref); /** * Check if a reference is a tag @@ -450,7 +617,17 @@ GIT_EXTERN(int) git_reference_is_remote(git_reference *ref); * @return 1 when the reference lives in the refs/tags * namespace; 0 otherwise. */ -GIT_EXTERN(int) git_reference_is_tag(git_reference *ref); +GIT_EXTERN(int) git_reference_is_tag(const git_reference *ref); + +/** + * Check if a reference is a note + * + * @param ref A git reference + * + * @return 1 when the reference lives in the refs/notes + * namespace; 0 otherwise. + */ +GIT_EXTERN(int) git_reference_is_note(const git_reference *ref); typedef enum { GIT_REF_FORMAT_NORMAL = 0u, @@ -490,7 +667,7 @@ typedef enum { * Once normalized, if the reference name is valid, it will be returned in * the user allocated buffer. * - * See `git_reference_create_symbolic()` for rules about valid names. + * See `git_reference_symbolic_create()` for rules about valid names. * * @param buffer_out User allocated buffer to store normalized name * @param buffer_size Size of buffer_out @@ -554,7 +731,7 @@ GIT_EXTERN(int) git_reference_is_valid_name(const char *refname); * @param ref a reference * @return the human-readable version of the name */ -GIT_EXTERN(const char *) git_reference_shorthand(git_reference *ref); +GIT_EXTERN(const char *) git_reference_shorthand(const git_reference *ref); /** @} */ diff --git a/include/git2/refspec.h b/include/git2/refspec.h index d96b83ce2..9acdc72d5 100644 --- a/include/git2/refspec.h +++ b/include/git2/refspec.h @@ -10,6 +10,7 @@ #include "common.h" #include "types.h" #include "net.h" +#include "buffer.h" /** * @file git2/refspec.h @@ -82,23 +83,21 @@ GIT_EXTERN(int) git_refspec_dst_matches(const git_refspec *refspec, const char * * Transform a reference to its target following the refspec's rules * * @param out where to store the target name - * @param outlen the size of the `out` buffer * @param spec the refspec * @param name the name of the reference to transform * @return 0, GIT_EBUFS or another error */ -GIT_EXTERN(int) git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name); +GIT_EXTERN(int) git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name); /** * Transform a target reference to its source reference following the refspec's rules * * @param out where to store the source reference name - * @param outlen the size of the `out` buffer * @param spec the refspec * @param name the name of the reference to transform * @return 0, GIT_EBUFS or another error */ -GIT_EXTERN(int) git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, const char *name); +GIT_EXTERN(int) git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name); GIT_END_DECL diff --git a/include/git2/remote.h b/include/git2/remote.h index 7410909dc..c72c9c8cc 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -62,10 +62,10 @@ GIT_EXTERN(int) git_remote_create_with_fetchspec( const char *fetch); /** - * Create a remote in memory + * Create an anonymous remote * - * Create a remote with the given refspec in memory. You can use - * this when you have a URL instead of a remote's name. Note that in-memory + * Create a remote with the given url and refspec in memory. You can use + * this when you have a URL instead of a remote's name. Note that anonymous * remotes cannot be converted to persisted remotes. * * The name, when provided, will be checked for validity. @@ -73,15 +73,15 @@ GIT_EXTERN(int) git_remote_create_with_fetchspec( * * @param out pointer to the new remote object * @param repo the associated repository - * @param fetch the fetch refspec to use for this remote. * @param url the remote repository's URL + * @param fetch the fetch refspec to use for this remote. * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_create_inmemory( +GIT_EXTERN(int) git_remote_create_anonymous( git_remote **out, git_repository *repo, - const char *fetch, - const char *url); + const char *url, + const char *fetch); /** * Get the information for a particular remote @@ -108,6 +108,18 @@ GIT_EXTERN(int) git_remote_load(git_remote **out, git_repository *repo, const ch GIT_EXTERN(int) git_remote_save(const git_remote *remote); /** + * Create a copy of an existing remote. All internal strings are also + * duplicated. Callbacks are not duplicated. + * + * Call `git_remote_free` to free the data. + * + * @param dest pointer where to store the copy + * @param source object to copy + * @return 0 or an error code + */ +GIT_EXTERN(int) git_remote_dup(git_remote **dest, git_remote *source); + +/** * Get the remote's repository * * @param remote the remote @@ -182,7 +194,7 @@ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec); * @param array pointer to the array in which to store the strings * @param remote the remote to query */ -GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote); +GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, const git_remote *remote); /** * Set the remote's list of fetch refspecs @@ -215,7 +227,7 @@ GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec); * @param array pointer to the array in which to store the strings * @param remote the remote to query */ -GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, git_remote *remote); +GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, const git_remote *remote); /** * Set the remote's list of push refspecs @@ -242,7 +254,7 @@ GIT_EXTERN(void) git_remote_clear_refspecs(git_remote *remote); * @param remote the remote * @return the amount of refspecs configured in this remote */ -GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote); +GIT_EXTERN(size_t) git_remote_refspec_count(const git_remote *remote); /** * Get a refspec from the remote @@ -251,7 +263,7 @@ GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote); * @param n the refspec to get * @return the nth refspec */ -GIT_EXTERN(const git_refspec *)git_remote_get_refspec(git_remote *remote, size_t n); +GIT_EXTERN(const git_refspec *)git_remote_get_refspec(const git_remote *remote, size_t n); /** * Open a connection to a remote @@ -307,7 +319,7 @@ GIT_EXTERN(int) git_remote_download(git_remote *remote); * @param remote the remote * @return 1 if it's connected, 0 otherwise. */ -GIT_EXTERN(int) git_remote_connected(git_remote *remote); +GIT_EXTERN(int) git_remote_connected(const git_remote *remote); /** * Cancel the operation @@ -343,9 +355,16 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote); * Update the tips to the new state * * @param remote the remote to update + * @param signature The identity to use when updating reflogs + * @param reflog_message The message to insert into the reflogs. If NULL, the + * default is "fetch <name>", where <name> is the name of + * the remote (or its url, for in-memory remotes). * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); +GIT_EXTERN(int) git_remote_update_tips( + git_remote *remote, + const git_signature *signature, + const char *reflog_message); /** * Download new data and update tips @@ -354,9 +373,15 @@ GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); * disconnect and update the remote-tracking branches. * * @param remote the remote to fetch from + * @param signature The identity to use when updating reflogs + * @param reflog_message The message to insert into the reflogs. If NULL, the + * default is "fetch" * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_fetch(git_remote *remote); +GIT_EXTERN(int) git_remote_fetch( + git_remote *remote, + const git_signature *signature, + const char *reflog_message); /** * Return whether a string is a valid remote URL @@ -432,7 +457,7 @@ struct git_remote_callbacks { * progress side-band will be passed to this function (this is * the 'counting objects' output. */ - int (*progress)(const char *str, int len, void *data); + git_transport_message_cb sideband_progress; /** * Completion is called when different parts of the download @@ -443,15 +468,18 @@ struct git_remote_callbacks { /** * This will be called if the remote host requires * authentication in order to connect to it. + * + * Returning GIT_PASSTHROUGH will make libgit2 behave as + * though this field isn't set. */ - int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); + git_cred_acquire_cb credentials; /** * During the download of new data, this will be regularly * called with the current count of progress done by the * indexer. */ - int (*transfer_progress)(const git_transfer_progress *stats, void *data); + git_transfer_progress_cb transfer_progress; /** * Each time a reference is updated locally, this function @@ -470,6 +498,18 @@ struct git_remote_callbacks { #define GIT_REMOTE_CALLBACKS_INIT {GIT_REMOTE_CALLBACKS_VERSION} /** + * Initializes a `git_remote_callbacks` with default values. Equivalent to + * creating an instance with GIT_REMOTE_CALLBACKS_INIT. + * + * @param opts the `git_remote_callbacks` struct to initialize + * @param version Version of struct; pass `GIT_REMOTE_CALLBACKS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_remote_init_callbacks( + git_remote_callbacks *opts, + unsigned int version); + +/** * Set the callbacks for a remote * * Note that the remote keeps its own copy of the data and you need to @@ -482,6 +522,17 @@ struct git_remote_callbacks { GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks); /** + * Retrieve the current callback structure + * + * This provides read access to the callbacks structure as the remote + * sees it. + * + * @param remote the remote to query + * @return a pointer to the callbacks structure + */ +GIT_EXTERN(const git_remote_callbacks *) git_remote_get_callbacks(git_remote *remote); + +/** * Get the statistics structure that is filled in by the fetch operation. */ GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote); @@ -498,7 +549,7 @@ typedef enum { * @param remote the remote to query * @return the auto-follow setting */ -GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(git_remote *remote); +GIT_EXTERN(git_remote_autotag_option_t) git_remote_autotag(const git_remote *remote); /** * Set the tag auto-follow setting @@ -521,18 +572,17 @@ GIT_EXTERN(void) git_remote_set_autotag( * * A temporary in-memory remote cannot be given a name with this method. * + * @param problems non-default refspecs cannot be renamed and will be + * stored here for further processing by the caller. Always free this + * strarray on succesful return. * @param remote the remote to rename * @param new_name the new name the remote should bear - * @param callback Optional callback to notify the consumer of fetch refspecs - * that haven't been automatically updated and need potential manual tweaking. - * @param payload Additional data to pass to the callback * @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code */ GIT_EXTERN(int) git_remote_rename( + git_strarray *problems, git_remote *remote, - const char *new_name, - git_remote_rename_problem_cb callback, - void *payload); + const char *new_name); /** * Retrieve the update FETCH_HEAD setting. @@ -559,6 +609,35 @@ GIT_EXTERN(void) git_remote_set_update_fetchhead(git_remote *remote, int value); */ GIT_EXTERN(int) git_remote_is_valid_name(const char *remote_name); +/** +* Delete an existing persisted remote. +* +* All remote-tracking branches and configuration settings +* for the remote will be removed. +* +* @param remote A valid remote +* @return 0 on success, or an error code. +*/ +GIT_EXTERN(int) git_remote_delete(git_remote *remote); + +/** + * Retrieve the name of the remote's default branch + * + * The default branch of a repository is the branch which HEAD points + * to. If the remote does not support reporting this information + * directly, it performs the guess as git does; that is, if there are + * multiple branches which point to the same commit, the first one is + * chosen. If the master branch is a candidate, it wins. + * + * This function must only be called after connecting. + * + * @param out the buffern in which to store the reference name + * @param remote the remote + * @return 0, GIT_ENOTFOUND if the remote does not have any references + * or none of them point to HEAD's commit, or an error message. + */ +GIT_EXTERN(int) git_remote_default_branch(git_buf *out, git_remote *remote); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/repository.h b/include/git2/repository.h index b4d561992..6a8ff4545 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -10,6 +10,7 @@ #include "common.h" #include "types.h" #include "oid.h" +#include "buffer.h" /** * @file git2/repository.h @@ -58,10 +59,8 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb); * The method will automatically detect if the repository is bare * (if there is a repository). * - * @param path_out The user allocated buffer which will - * contain the found path. - * - * @param path_size repository_path size + * @param out A pointer to a user-allocated git_buf which will contain + * the found path. * * @param start_path The base path where the lookup starts. * @@ -77,8 +76,7 @@ GIT_EXTERN(int) git_repository_wrap_odb(git_repository **out, git_odb *odb); * @return 0 or an error code */ GIT_EXTERN(int) git_repository_discover( - char *path_out, - size_t path_size, + git_buf *out, const char *start_path, int across_fs, const char *ceiling_dirs); @@ -270,6 +268,18 @@ typedef struct { #define GIT_REPOSITORY_INIT_OPTIONS_INIT {GIT_REPOSITORY_INIT_OPTIONS_VERSION} /** + * Initializes a `git_repository_init_options` with default values. Equivalent + * to creating an instance with GIT_REPOSITORY_INIT_OPTIONS_INIT. + * + * @param opts the `git_repository_init_options` struct to initialize + * @param version Version of struct; pass `GIT_REPOSITORY_INIT_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_repository_init_init_options( + git_repository_init_options *opts, + unsigned int version); + +/** * Create a new Git repository in the given folder with extended controls. * * This will initialize a new git repository (creating the repo_path @@ -398,13 +408,29 @@ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo); * The configuration file must be freed once it's no longer * being used by the user. * - * @param out Pointer to store the loaded config file + * @param out Pointer to store the loaded configuration * @param repo A repository object * @return 0, or an error code */ GIT_EXTERN(int) git_repository_config(git_config **out, git_repository *repo); /** + * Get a snapshot of the repository's configuration + * + * Convenience function to take a snapshot from the repository's + * configuration. The contents of this snapshot will not change, + * even if the underlying config files are modified. + * + * The configuration file must be freed once it's no longer + * being used by the user. + * + * @param out Pointer to store the loaded configuration + * @param repo the repository + * @return 0, or an error code + */ +GIT_EXTERN(int) git_repository_config_snapshot(git_config **out, git_repository *repo); + +/** * Get the Object Database for this repository. * * If a custom ODB has not been set, the default @@ -464,21 +490,11 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo); * Use this function to get the contents of this file. Don't forget to * remove the file after you create the commit. * - * If the repository message exists and there are no errors reading it, this - * returns the bytes needed to store the message in memory (i.e. message - * file size plus one terminating NUL byte). That value is returned even if - * `out` is NULL or `len` is shorter than the necessary size. - * - * The `out` buffer will *always* be NUL terminated, even if truncation - * occurs. - * - * @param out Buffer to write data into or NULL to just read required size - * @param len Length of `out` buffer in bytes + * @param out git_buf to write data into * @param repo Repository to read prepared message from - * @return GIT_ENOTFOUND if no message exists, other value < 0 for other - * errors, or total bytes in message (may be > `len`) on success + * @return 0, GIT_ENOTFOUND if no message exists or an error code */ -GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *repo); +GIT_EXTERN(int) git_repository_message(git_buf *out, git_repository *repo); /** * Remove git's prepared message. @@ -488,13 +504,13 @@ GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *re GIT_EXTERN(int) git_repository_message_remove(git_repository *repo); /** - * Remove all the metadata associated with an ongoing git merge, including - * MERGE_HEAD, MERGE_MSG, etc. + * Remove all the metadata associated with an ongoing command like merge, + * revert, cherry-pick, etc. For example: MERGE_HEAD, MERGE_MSG, etc. * * @param repo A repository object * @return 0 on success, or error */ -GIT_EXTERN(int) git_repository_merge_cleanup(git_repository *repo); +GIT_EXTERN(int) git_repository_state_cleanup(git_repository *repo); typedef int (*git_repository_fetchhead_foreach_cb)(const char *ref_name, const char *remote_url, @@ -503,14 +519,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 +538,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); @@ -538,6 +562,10 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo, * hash a file in the repository and you want to apply filtering rules (e.g. * crlf filters) before generating the SHA, then use this function. * + * Note: if the repository has `core.safecrlf` set to fail and the + * filtering triggers that failure, then this function will return an + * error and not calculate the hash of the file. + * * @param out Output value of calculated SHA * @param repo Repository pointer * @param path Path to file on disk whose contents should be hashed. If the @@ -547,6 +575,7 @@ GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo, * NULL, then the `path` parameter will be used instead. If * this is passed as the empty string, then no filters will be * applied when calculating the hash. + * @return 0 on success, or an error code */ GIT_EXTERN(int) git_repository_hashfile( git_oid *out, @@ -571,11 +600,15 @@ GIT_EXTERN(int) git_repository_hashfile( * * @param repo Repository pointer * @param refname Canonical name of the reference the HEAD should point at + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog * @return 0 on success, or an error code */ GIT_EXTERN(int) git_repository_set_head( git_repository* repo, - const char* refname); + const char* refname, + const git_signature *signature, + const char *log_message); /** * Make the repository HEAD directly point to the Commit. @@ -591,11 +624,15 @@ GIT_EXTERN(int) git_repository_set_head( * * @param repo Repository pointer * @param commitish Object id of the Commit the HEAD should point to + * @param signature The identity that will used to populate the reflog entry + * @param log_message The one line long message to be appended to the reflog * @return 0 on success, or an error code */ GIT_EXTERN(int) git_repository_set_head_detached( git_repository* repo, - const git_oid* commitish); + const git_oid* commitish, + const git_signature *signature, + const char *log_message); /** * Detach the HEAD. @@ -611,11 +648,15 @@ GIT_EXTERN(int) git_repository_set_head_detached( * Otherwise, the HEAD will be detached and point to the peeled Commit. * * @param repo Repository pointer + * @param signature The identity that will used to populate the reflog entry + * @param reflog_message The one line long message to be appended to the reflog * @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing * branch or an error code */ GIT_EXTERN(int) git_repository_detach_head( - git_repository* repo); + git_repository* repo, + const git_signature *signature, + const char *reflog_message); typedef enum { GIT_REPOSITORY_STATE_NONE, diff --git a/include/git2/reset.h b/include/git2/reset.h index c36781722..b8c580339 100644 --- a/include/git2/reset.h +++ b/include/git2/reset.h @@ -19,9 +19,9 @@ GIT_BEGIN_DECL * Kinds of reset operation */ typedef enum { - GIT_RESET_SOFT = 1, /** Move the head to the given commit */ - GIT_RESET_MIXED = 2, /** SOFT plus reset index to the commit */ - GIT_RESET_HARD = 3, /** MIXED plus changes in working tree discarded */ + GIT_RESET_SOFT = 1, /**< Move the head to the given commit */ + GIT_RESET_MIXED = 2, /**< SOFT plus reset index to the commit */ + GIT_RESET_HARD = 3, /**< MIXED plus changes in working tree discarded */ } git_reset_t; /** @@ -48,10 +48,21 @@ typedef enum { * * @param reset_type Kind of reset operation to perform. * + * @param signature The identity that will used to populate the reflog entry + * + * @param log_message The one line long message to be appended to the reflog. + * The reflog is only updated if the affected direct reference is actually + * changing. If NULL, the default is "reset: moving"; if you want something more + * useful, provide a message. + * * @return 0 on success or an error code */ GIT_EXTERN(int) git_reset( - git_repository *repo, git_object *target, git_reset_t reset_type); + git_repository *repo, + git_object *target, + git_reset_t reset_type, + git_signature *signature, + const char *log_message); /** * Updates some entries in the index from the target commit tree. diff --git a/include/git2/revert.h b/include/git2/revert.h new file mode 100644 index 000000000..fc1767c93 --- /dev/null +++ b/include/git2/revert.h @@ -0,0 +1,86 @@ +/* + * 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. + */ +#ifndef INCLUDE_git_revert_h__ +#define INCLUDE_git_revert_h__ + +#include "common.h" +#include "types.h" +#include "merge.h" + +/** + * @file git2/revert.h + * @brief Git revert routines + * @defgroup git_revert Git revert routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +typedef struct { + unsigned int version; + + /** For merge commits, the "mainline" is treated as the parent. */ + unsigned int mainline; + + git_merge_options merge_opts; + git_checkout_options checkout_opts; +} git_revert_options; + +#define GIT_REVERT_OPTIONS_VERSION 1 +#define GIT_REVERT_OPTIONS_INIT {GIT_REVERT_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT} + +/** + * Initializes a `git_revert_options` with default values. Equivalent to + * creating an instance with GIT_REVERT_OPTIONS_INIT. + * + * @param opts the `git_revert_options` struct to initialize + * @param version Version of struct; pass `GIT_REVERT_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_revert_init_options( + git_revert_options *opts, + unsigned int version); + +/** + * Reverts the given commit against the given "our" commit, producing an + * index that reflects the result of the revert. + * + * The returned index must be freed explicitly with `git_index_free`. + * + * @param out pointer to store the index result in + * @param repo the repository that contains the given commits + * @param revert_commit the commit to revert + * @param our_commit the commit to revert against (eg, HEAD) + * @param mainline the parent of the revert commit, if it is a merge + * @param merge_options the merge options (or null for defaults) + * @return zero on success, -1 on failure. + */ +int git_revert_commit( + git_index **out, + git_repository *repo, + git_commit *revert_commit, + git_commit *our_commit, + unsigned int mainline, + const git_merge_options *merge_options); + +/** + * Reverts the given commit, producing changes in the working directory. + * + * @param repo the repository to revert + * @param commit the commit to revert + * @param given_opts merge flags + * @return zero on success, -1 on failure. + */ +GIT_EXTERN(int) git_revert( + git_repository *repo, + git_commit *commit, + const git_revert_options *given_opts); + +/** @} */ +GIT_END_DECL +#endif + diff --git a/include/git2/revwalk.h b/include/git2/revwalk.h index c59b79938..1bd6186f3 100644 --- a/include/git2/revwalk.h +++ b/include/git2/revwalk.h @@ -87,7 +87,7 @@ GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker); /** * Mark a commit to start traversal from. * - * The given OID must belong to a commit on the walked + * The given OID must belong to a committish on the walked * repository. * * The given commit will be used as one of the roots @@ -108,7 +108,10 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *id); * pattern will be pushed to the revision walker. * * A leading 'refs/' is implied if not present as well as a trailing - * '/ *' if the glob lacks '?', '*' or '['. + * '/\*' if the glob lacks '?', '\*' or '['. + * + * Any references matching this glob which do not point to a + * committish will be ignored. * * @param walk the walker being used for the traversal * @param glob the glob pattern references should match @@ -127,7 +130,7 @@ GIT_EXTERN(int) git_revwalk_push_head(git_revwalk *walk); /** * Mark a commit (and its ancestors) uninteresting for the output. * - * The given OID must belong to a commit on the walked + * The given OID must belong to a committish on the walked * repository. * * The resolved commit and all its parents will be hidden from the @@ -147,7 +150,10 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *commit_id); * revision walk. * * A leading 'refs/' is implied if not present as well as a trailing - * '/ *' if the glob lacks '?', '*' or '['. + * '/\*' if the glob lacks '?', '\*' or '['. + * + * Any references matching this glob which do not point to a + * committish will be ignored. * * @param walk the walker being used for the traversal * @param glob the glob pattern references should match @@ -166,7 +172,7 @@ GIT_EXTERN(int) git_revwalk_hide_head(git_revwalk *walk); /** * Push the OID pointed to by a reference * - * The reference must point to a commit. + * The reference must point to a committish. * * @param walk the walker being used for the traversal * @param refname the reference to push @@ -177,7 +183,7 @@ GIT_EXTERN(int) git_revwalk_push_ref(git_revwalk *walk, const char *refname); /** * Hide the OID pointed to by a reference * - * The reference must point to a commit. + * The reference must point to a committish. * * @param walk the walker being used for the traversal * @param refname the reference to hide @@ -255,6 +261,30 @@ GIT_EXTERN(void) git_revwalk_free(git_revwalk *walk); */ GIT_EXTERN(git_repository *) git_revwalk_repository(git_revwalk *walk); +/** + * This is a callback function that user can provide to hide a + * commit and its parents. If the callback function returns non-zero value, + * then this commit and its parents will be hidden. + * + * @param commit_id oid of Commit + * @param payload User-specified pointer to data to be passed as data payload + */ +typedef int(*git_revwalk_hide_cb)( + const git_oid *commit_id, + void *payload); + +/** + * Adds a callback function to hide a commit and its parents + * + * @param walk the revision walker + * @param hide_cb callback function to hide a commit and its parents + * @param payload data payload to be passed to callback function + */ +GIT_EXTERN(int) git_revwalk_add_hide_cb( + git_revwalk *walk, + git_revwalk_hide_cb hide_cb, + void *payload); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/signature.h b/include/git2/signature.h index 2fa46d032..feb1b4073 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -68,10 +68,11 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo) * * Call `git_signature_free()` to free the data. * - * @param sig signature to duplicated - * @return a copy of sig, NULL on out of memory + * @param dest pointer where to store the copy + * @param sig signature to duplicate + * @return 0 or an error code */ -GIT_EXTERN(git_signature *) git_signature_dup(const git_signature *sig); +GIT_EXTERN(int) git_signature_dup(git_signature **dest, const git_signature *sig); /** * Free an existing signature. diff --git a/include/git2/stash.h b/include/git2/stash.h index b48d33f5d..e2fe2cf0b 100644 --- a/include/git2/stash.h +++ b/include/git2/stash.h @@ -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, diff --git a/include/git2/status.h b/include/git2/status.h index 4ec3432df..effe5e1ea 100644 --- a/include/git2/status.h +++ b/include/git2/status.h @@ -121,6 +121,11 @@ typedef enum { * - GIT_STATUS_OPT_NO_REFRESH bypasses the default status behavior of * doing a "soft" index reload (i.e. reloading the index data if the * file on disk has been modified outside libgit2). + * - GIT_STATUS_OPT_UPDATE_INDEX tells libgit2 to refresh the stat cache + * in the index for files that are unchanged but have out of date stat + * information in the index. It will result in less work being done on + * subsequent calls to get status. This is mutually exclusive with the + * NO_REFRESH option. * * Calling `git_status_foreach()` is like calling the extended version * with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED, @@ -141,6 +146,7 @@ typedef enum { GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10), GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11), GIT_STATUS_OPT_NO_REFRESH = (1u << 12), + GIT_STATUS_OPT_UPDATE_INDEX = (1u << 13), } git_status_opt_t; #define GIT_STATUS_OPT_DEFAULTS \ @@ -175,6 +181,18 @@ typedef struct { #define GIT_STATUS_OPTIONS_INIT {GIT_STATUS_OPTIONS_VERSION} /** + * Initializes a `git_status_options` with default values. Equivalent to + * creating an instance with GIT_STATUS_OPTIONS_INIT. + * + * @param opts The `git_status_options` instance to initialize. + * @param version Version of struct; pass `GIT_STATUS_OPTIONS_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_status_init_options( + git_status_options *opts, + unsigned int version); + +/** * A status entry, providing the differences between the file as it exists * in HEAD and the index, and providing the differences between the index * and the working directory. @@ -203,12 +221,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, @@ -223,11 +241,16 @@ GIT_EXTERN(int) git_status_foreach( * in what order. See the `git_status_options` structure for details * about the additional controls that this makes available. * + * Note that if a `pathspec` is given in the `git_status_options` to filter + * the status, then the results from rename detection (if you enable it) may + * not be accurate. To do rename detection properly, this must be called + * with no `pathspec` so that all files can be considered. + * * @param repo Repository object * @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, @@ -238,8 +261,20 @@ GIT_EXTERN(int) git_status_foreach_ext( /** * Get file status for a single file. * - * This is not quite the same as calling `git_status_foreach_ext()` with - * the pathspec set to the specified path. + * This tries to get status for the filename that you give. If no files + * match that name (in either the HEAD, index, or working directory), this + * returns GIT_ENOTFOUND. + * + * If the name matches multiple files (for example, if the `path` names a + * directory or if running on a case- insensitive filesystem and yet the + * HEAD has two entries that both match the path), then this returns + * GIT_EAMBIGUOUS because it cannot give correct results. + * + * This does not do any sort of rename detection. Renames require a set of + * targets and because of the path filtering, there is not enough + * information to check renames correctly. To check file status with rename + * detection, there is no choice but to do a full `git_status_list_new` and + * scan through looking for the path that you are interested in. * * @param status_flags Output combination of git_status_t values for file * @param repo A repository object @@ -256,6 +291,11 @@ GIT_EXTERN(int) git_status_file( /** * Gather file status information and populate the `git_status_list`. * + * Note that if a `pathspec` is given in the `git_status_options` to filter + * the status, then the results from rename detection (if you enable it) may + * not be accurate. To do rename detection properly, this must be called + * with no `pathspec` so that all files can be considered. + * * @param out Pointer to store the status results in * @param repo Repository object * @param opts Status options structure @@ -269,6 +309,9 @@ GIT_EXTERN(int) git_status_list_new( /** * Gets the count of status entries in this list. * + * If there are no changes in status (at least according the options given + * when the status list was created), this can return 0. + * * @param statuslist Existing status list object * @return the number of status entries */ diff --git a/include/git2/submodule.h b/include/git2/submodule.h index 186f263f5..864d1c58c 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -97,7 +97,8 @@ typedef enum { (((S) & GIT_SUBMODULE_STATUS__INDEX_FLAGS) == 0) #define GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(S) \ - (((S) & GIT_SUBMODULE_STATUS__WD_FLAGS) == 0) + (((S) & (GIT_SUBMODULE_STATUS__WD_FLAGS & \ + ~GIT_SUBMODULE_STATUS_WD_UNINITIALIZED)) == 0) #define GIT_SUBMODULE_STATUS_IS_WD_DIRTY(S) \ (((S) & (GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED | \ @@ -114,30 +115,36 @@ typedef enum { * * - The submodule is not mentioned in the HEAD, the index, and the config, * but does "exist" in the working directory (i.e. there is a subdirectory - * that is a valid self-contained git repo). In this case, this function - * returns GIT_EEXISTS to indicate the the submodule exists but not in a + * that appears to be a Git repository). In this case, this function + * returns GIT_EEXISTS to indicate a sub-repository exists but not in a * state where a git_submodule can be instantiated. * - The submodule is not mentioned in the HEAD, index, or config and the * working directory doesn't contain a value git repo at that path. * There may or may not be anything else at that path, but nothing that * looks like a submodule. In this case, this returns GIT_ENOTFOUND. * - * The submodule object is owned by the containing repo and will be freed - * when the repo is freed. The caller need not free the submodule. + * You must call `git_submodule_free` when done with the submodule. * - * @param submodule Pointer to submodule description object pointer.. - * @param repo The repository. - * @param name The name of the submodule. Trailing slashes will be ignored. + * @param out Output ptr to submodule; pass NULL to just get return code + * @param repo The parent repository + * @param name The name of or path to the submodule; trailing slashes okay * @return 0 on success, GIT_ENOTFOUND if submodule does not exist, - * GIT_EEXISTS if submodule exists in working directory only, -1 on - * other errors. + * GIT_EEXISTS if a repository is found in working directory only, + * -1 on other errors. */ GIT_EXTERN(int) git_submodule_lookup( - git_submodule **submodule, + git_submodule **out, git_repository *repo, const char *name); /** + * Release a submodule + * + * @param submodule Submodule object + */ +GIT_EXTERN(void) git_submodule_free(git_submodule *submodule); + +/** * Iterate over all tracked submodules of a repository. * * See the note on `git_submodule` above. This iterates over the tracked @@ -174,9 +181,11 @@ GIT_EXTERN(int) git_submodule_foreach( * `git_submodule_add_finalize()` to wrap up adding the new submodule and * .gitmodules to the index to be ready to commit. * - * @param submodule The newly created submodule ready to open for clone - * @param repo Superproject repository to contain the new submodule - * @param url URL for the submodules remote + * You must call `git_submodule_free` on the submodule object when done. + * + * @param out The newly created submodule ready to open for clone + * @param repo The repository in which you want to create the submodule + * @param url URL for the submodule's remote * @param path Path at which the submodule should be created * @param use_gitlink Should workdir contain a gitlink to the repo in * .git/modules vs. repo directly in workdir. @@ -184,7 +193,7 @@ GIT_EXTERN(int) git_submodule_foreach( * -1 on other errors. */ GIT_EXTERN(int) git_submodule_add_setup( - git_submodule **submodule, + git_submodule **out, git_repository *repo, const char *url, const char *path, @@ -271,6 +280,24 @@ GIT_EXTERN(const char *) git_submodule_path(git_submodule *submodule); GIT_EXTERN(const char *) git_submodule_url(git_submodule *submodule); /** + * Resolve a submodule url relative to the given repository. + * + * @param out buffer to store the absolute submodule url in + * @param repo Pointer to repository object + * @param url Relative url + * @return 0 or an error code + */ +GIT_EXTERN(int) git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *url); + +/** +* Get the branch for the submodule. +* +* @param submodule Pointer to submodule object +* @return Pointer to the submodule branch +*/ +GIT_EXTERN(const char *) git_submodule_branch(git_submodule *submodule); + +/** * Set the URL for the submodule. * * This sets the URL in memory for the submodule. This will be used for @@ -410,7 +437,7 @@ GIT_EXTERN(git_submodule_update_t) git_submodule_set_update( * * @return 0 if fetchRecurseSubmodules is false, 1 if true */ -GIT_EXTERN(int) git_submodule_fetch_recurse_submodules( +GIT_EXTERN(git_submodule_recurse_t) git_submodule_fetch_recurse_submodules( git_submodule *submodule); /** @@ -424,9 +451,9 @@ GIT_EXTERN(int) git_submodule_fetch_recurse_submodules( * @param fetch_recurse_submodules Boolean value * @return old value for fetchRecurseSubmodules */ -GIT_EXTERN(int) git_submodule_set_fetch_recurse_submodules( +GIT_EXTERN(git_submodule_recurse_t) git_submodule_set_fetch_recurse_submodules( git_submodule *submodule, - int fetch_recurse_submodules); + git_submodule_recurse_t fetch_recurse_submodules); /** * Copy submodule info into ".git/config" file. @@ -474,15 +501,23 @@ GIT_EXTERN(int) git_submodule_open( * * Call this to reread cached submodule information for this submodule if * you have reason to believe that it has changed. + * + * @param submodule The submodule to reload + * @param force Force reload even if the data doesn't seem out of date + * @return 0 on success, <0 on error */ -GIT_EXTERN(int) git_submodule_reload(git_submodule *submodule); +GIT_EXTERN(int) git_submodule_reload(git_submodule *submodule, int force); /** * Reread all submodule info. * * Call this to reload all cached submodule information for the repo. + * + * @param repo The repository to reload submodule data for + * @param force Force full reload even if the data doesn't seem out of date + * @return 0 on success, <0 on error */ -GIT_EXTERN(int) git_submodule_reload_all(git_repository *repo); +GIT_EXTERN(int) git_submodule_reload_all(git_repository *repo, int force); /** * Get the status for a submodule. diff --git a/include/git2/sys/commit.h b/include/git2/sys/commit.h index 34a12fb15..627d3ae2e 100644 --- a/include/git2/sys/commit.h +++ b/include/git2/sys/commit.h @@ -21,16 +21,18 @@ GIT_BEGIN_DECL /** - * Create new commit in the repository from a list of `git_oid` values + * Create new commit in the repository from a list of `git_oid` values. * * See documentation for `git_commit_create()` for information about the * parameters, as the meaning is identical excepting that `tree` and * `parents` now take `git_oid`. This is a dangerous API in that nor * the `tree`, neither the `parents` list of `git_oid`s are checked for * validity. + * + * @see git_commit_create */ -GIT_EXTERN(int) git_commit_create_from_oids( - git_oid *oid, +GIT_EXTERN(int) git_commit_create_from_ids( + git_oid *id, git_repository *repo, const char *update_ref, const git_signature *author, @@ -38,9 +40,41 @@ GIT_EXTERN(int) git_commit_create_from_oids( const char *message_encoding, const char *message, const git_oid *tree, - int parent_count, + size_t parent_count, const git_oid *parents[]); +/** + * Callback function to return parents for commit. + * + * This is invoked with the count of the number of parents processed so far + * along with the user supplied payload. This should return a git_oid of + * the next parent or NULL if all parents have been provided. + */ +typedef const git_oid *(*git_commit_parent_callback)(size_t idx, void *payload); + +/** + * Create a new commit in the repository with an callback to supply parents. + * + * See documentation for `git_commit_create()` for information about the + * parameters, as the meaning is identical excepting that `tree` takes a + * `git_oid` and doesn't check for validity, and `parent_cb` is invoked + * with `parent_payload` and should return `git_oid` values or NULL to + * indicate that all parents are accounted for. + * + * @see git_commit_create + */ +GIT_EXTERN(int) git_commit_create_from_callback( + git_oid *id, + git_repository *repo, + const char *update_ref, + const git_signature *author, + const git_signature *committer, + const char *message_encoding, + const char *message, + const git_oid *tree, + git_commit_parent_callback parent_cb, + void *parent_payload); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 419ad7ea7..85e0d6417 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -57,19 +57,33 @@ struct git_config_backend { /* Open means open the file/database and parse if necessary */ int (*open)(struct git_config_backend *, git_config_level_t level); - int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry); + int (*get)(struct git_config_backend *, const char *key, const git_config_entry **entry); int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); int (*del_multivar)(struct git_config_backend *, const char *key, const char *regexp); int (*iterator)(git_config_iterator **, struct git_config_backend *); int (*refresh)(struct git_config_backend *); + /** Produce a read-only version of this backend */ + int (*snapshot)(struct git_config_backend **, struct git_config_backend *); void (*free)(struct git_config_backend *); }; #define GIT_CONFIG_BACKEND_VERSION 1 #define GIT_CONFIG_BACKEND_INIT {GIT_CONFIG_BACKEND_VERSION} /** + * Initializes a `git_config_backend` with default values. Equivalent to + * creating an instance with GIT_CONFIG_BACKEND_INIT. + * + * @param opts the `git_config_backend` struct to initialize. + * @param version Version of struct; pass `GIT_CONFIG_BACKEND_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_config_init_backend( + git_config_backend *backend, + unsigned int version); + +/** * Add a generic config file instance to an existing config * * Note that the configuration object will free the file diff --git a/include/git2/sys/diff.h b/include/git2/sys/diff.h new file mode 100644 index 000000000..48d72f4f9 --- /dev/null +++ b/include/git2/sys/diff.h @@ -0,0 +1,91 @@ +/* + * 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. + */ +#ifndef INCLUDE_sys_git_diff_h__ +#define INCLUDE_sys_git_diff_h__ + +#include "git2/common.h" +#include "git2/types.h" +#include "git2/oid.h" +#include "git2/diff.h" +#include "git2/status.h" + +/** + * @file git2/sys/diff.h + * @brief Low-level Git diff utilities + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Diff print callback that writes to a git_buf. + * + * This function is provided not for you to call it directly, but instead + * so you can use it as a function pointer to the `git_diff_print` or + * `git_patch_print` APIs. When using those APIs, you specify a callback + * to actually handle the diff and/or patch data. + * + * Use this callback to easily write that data to a `git_buf` buffer. You + * must pass a `git_buf *` value as the payload to the `git_diff_print` + * and/or `git_patch_print` function. The data will be appended to the + * buffer (after any existing content). + */ +GIT_EXTERN(int) git_diff_print_callback__to_buf( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload); /*< payload must be a `git_buf *` */ + +/** + * Diff print callback that writes to stdio FILE handle. + * + * This function is provided not for you to call it directly, but instead + * so you can use it as a function pointer to the `git_diff_print` or + * `git_patch_print` APIs. When using those APIs, you specify a callback + * to actually handle the diff and/or patch data. + * + * Use this callback to easily write that data to a stdio FILE handle. You + * must pass a `FILE *` value (such as `stdout` or `stderr` or the return + * value from `fopen()`) as the payload to the `git_diff_print` + * and/or `git_patch_print` function. If you pass NULL, this will write + * data to `stdout`. + */ +GIT_EXTERN(int) git_diff_print_callback__to_file_handle( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload); /*< payload must be a `FILE *` */ + + +typedef struct { + unsigned int version; + size_t stat_calls; + size_t oid_calculations; +} git_diff_perfdata; + +#define GIT_DIFF_PERFDATA_VERSION 1 +#define GIT_DIFF_PERFDATA_INIT {GIT_DIFF_PERFDATA_VERSION,0,0} + +/** + * Get performance data for a diff object. + * + * @param out Structure to be filled with diff performance data + * @param diff Diff to read performance data from + * @return 0 for success, <0 for error + */ +GIT_EXTERN(int) git_diff_get_perfdata( + git_diff_perfdata *out, const git_diff *diff); + +/** + * Get performance data for diffs from a git_status_list + */ +GIT_EXTERN(int) git_status_list_get_perfdata( + git_diff_perfdata *out, const git_status_list *status); + +/** @} */ +GIT_END_DECL +#endif diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index 94ad3aed4..60248271a 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -55,7 +55,10 @@ GIT_EXTERN(git_filter *) git_filter_lookup(const char *name); * your own chains of filters. */ GIT_EXTERN(int) git_filter_list_new( - git_filter_list **out, git_repository *repo, git_filter_mode_t mode); + git_filter_list **out, + git_repository *repo, + git_filter_mode_t mode, + uint32_t options); /** * Add a filter to a filter list with the given payload. @@ -115,10 +118,15 @@ GIT_EXTERN(uint16_t) git_filter_source_filemode(const git_filter_source *src); GIT_EXTERN(const git_oid *) git_filter_source_id(const git_filter_source *src); /** - * Get the git_filter_mode_t to be applied + * Get the git_filter_mode_t to be used */ GIT_EXTERN(git_filter_mode_t) git_filter_source_mode(const git_filter_source *src); +/** + * Get the combination git_filter_opt_t options to be applied + */ +GIT_EXTERN(uint32_t) git_filter_source_options(const git_filter_source *src); + /* * struct git_filter * @@ -149,6 +157,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. */ diff --git a/include/git2/sys/mempack.h b/include/git2/sys/mempack.h new file mode 100644 index 000000000..d3bc87b4d --- /dev/null +++ b/include/git2/sys/mempack.h @@ -0,0 +1,85 @@ +/* + * 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. + */ +#ifndef INCLUDE_sys_git_odb_mempack_h__ +#define INCLUDE_sys_git_odb_mempack_h__ + +#include "git2/common.h" +#include "git2/types.h" +#include "git2/oid.h" +#include "git2/odb.h" + +/** + * @file git2/sys/mempack.h + * @brief Custom ODB backend that permits packing objects in-memory + * @defgroup git_backend Git custom backend APIs + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Instantiate a new mempack backend. + * + * The backend must be added to an existing ODB with the highest + * priority. + * + * git_mempack_new(&mempacker); + * git_repository_odb(&odb, repository); + * git_odb_add_backend(odb, mempacker, 999); + * + * Once the backend has been loaded, all writes to the ODB will + * instead be queued in memory, and can be finalized with + * `git_mempack_dump`. + * + * Subsequent reads will also be served from the in-memory store + * to ensure consistency, until the memory store is dumped. + * + * @param out Poiter where to store the ODB backend + * @return 0 on success; error code otherwise + */ +int git_mempack_new(git_odb_backend **out); + +/** + * Dump all the queued in-memory writes to a packfile. + * + * The contents of the packfile will be stored in the given buffer. + * It is the caller's responsability to ensure that the generated + * packfile is available to the repository (e.g. by writing it + * to disk, or doing something crazy like distributing it across + * several copies of the repository over a network). + * + * Once the generated packfile is available to the repository, + * call `git_mempack_reset` to cleanup the memory store. + * + * Calling `git_mempack_reset` before the packfile has been + * written to disk will result in an inconsistent repository + * (the objects in the memory store won't be accessible). + * + * @param pack Buffer where to store the raw packfile + * @param repo The active repository where the backend is loaded + * @param backend The mempack backend + * @return 0 on success; error code otherwise + */ +int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *backend); + +/** + * Reset the memory packer by clearing all the queued objects. + * + * This assumes that `git_mempack_dump` has been called before to + * store all the queued objects into a single packfile. + * + * Alternatively, call `reset` without a previous dump to "undo" + * all the recently written objects, giving transaction-like + * semantics to the Git repository. + * + * @param backend The mempack backend + */ +void git_mempack_reset(git_odb_backend *backend); + +GIT_END_DECL + +#endif diff --git a/include/git2/sys/odb_backend.h b/include/git2/sys/odb_backend.h index 8039a5b82..1fc3c3159 100644 --- a/include/git2/sys/odb_backend.h +++ b/include/git2/sys/odb_backend.h @@ -35,11 +35,8 @@ struct git_odb_backend { int (* read)( void **, size_t *, git_otype *, git_odb_backend *, const git_oid *); - /* To find a unique object given a prefix - * of its oid. - * The oid given must be so that the - * remaining (GIT_OID_HEXSZ - len)*4 bits - * are 0s. + /* To find a unique object given a prefix of its oid. The oid given + * must be so that the remaining (GIT_OID_HEXSZ - len)*4 bits are 0s. */ int (* read_prefix)( git_oid *, void **, size_t *, git_otype *, @@ -64,6 +61,9 @@ struct git_odb_backend { int (* exists)( git_odb_backend *, const git_oid *); + int (* exists_prefix)( + git_oid *, git_odb_backend *, const git_oid *, size_t); + /** * If the backend implements a refreshing mechanism, it should be exposed * through this endpoint. Each call to `git_odb_refresh()` will invoke it. @@ -81,7 +81,7 @@ struct git_odb_backend { int (* writepack)( git_odb_writepack **, git_odb_backend *, git_odb *odb, - git_transfer_progress_callback progress_cb, void *progress_payload); + git_transfer_progress_cb progress_cb, void *progress_payload); void (* free)(git_odb_backend *); }; @@ -89,6 +89,18 @@ struct git_odb_backend { #define GIT_ODB_BACKEND_VERSION 1 #define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION} +/** + * Initializes a `git_odb_backend` with default values. Equivalent to + * creating an instance with GIT_ODB_BACKEND_INIT. + * + * @param opts the `git_odb_backend` struct to initialize. + * @param version Version the struct; pass `GIT_ODB_BACKEND_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_odb_init_backend( + git_odb_backend *backend, + unsigned int version); + GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len); GIT_END_DECL diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h index 9cf5073fb..3b216a287 100644 --- a/include/git2/sys/refdb_backend.h +++ b/include/git2/sys/refdb_backend.h @@ -93,17 +93,20 @@ struct git_refdb_backend { * must provide this function. */ int (*write)(git_refdb_backend *backend, - const git_reference *ref, int force); + const git_reference *ref, int force, + const git_signature *who, const char *message, + const git_oid *old, const char *old_target); int (*rename)( git_reference **out, git_refdb_backend *backend, - const char *old_name, const char *new_name, int force); + const char *old_name, const char *new_name, int force, + const git_signature *who, const char *message); /** * Deletes the given reference from the refdb. A refdb implementation * must provide this function. */ - int (*del)(git_refdb_backend *backend, const char *ref_name); + int (*del)(git_refdb_backend *backend, const char *ref_name, const git_oid *old_id, const char *old_target); /** * Suggests that the given refdb compress or optimize its references. @@ -115,6 +118,17 @@ struct git_refdb_backend { int (*compress)(git_refdb_backend *backend); /** + * Query whether a particular reference has a log (may be empty) + */ + int (*has_log)(git_refdb_backend *backend, const char *refname); + + /** + * Make sure a particular reference will have a reflog which + * will be appended to on writes. + */ + int (*ensure_log)(git_refdb_backend *backend, const char *refname); + + /** * Frees any resources held by the refdb. A refdb implementation may * provide this function; if it is not provided, nothing will be done. */ @@ -145,6 +159,18 @@ struct git_refdb_backend { #define GIT_REFDB_BACKEND_INIT {GIT_REFDB_BACKEND_VERSION} /** + * Initializes a `git_refdb_backend` with default values. Equivalent to + * creating an instance with GIT_REFDB_BACKEND_INIT. + * + * @param opts the `git_refdb_backend` struct to initialize + * @param version Version of struct; pass `GIT_REFDB_BACKEND_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_refdb_init_backend( + git_refdb_backend *backend, + unsigned int version); + +/** * Constructors for default filesystem-based refdb backend * * Under normal usage, this is called for you when the repository is diff --git a/include/git2/transport.h b/include/git2/transport.h index caabd0465..af7812b5d 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -41,6 +41,9 @@ typedef enum { /* git_cred_default */ GIT_CREDTYPE_DEFAULT = (1u << 3), + + /* git_cred_ssh_interactive */ + GIT_CREDTYPE_SSH_INTERACTIVE = (1u << 4), } git_credtype_t; /* The base structure for all credential types */ @@ -60,8 +63,10 @@ typedef struct { #ifdef GIT_SSH typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback)); +typedef LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*git_cred_ssh_interactive_callback)); #else typedef int (*git_cred_sign_callback)(void *, ...); +typedef int (*git_cred_ssh_interactive_callback)(void *, ...); #endif /** @@ -76,6 +81,16 @@ typedef struct git_cred_ssh_key { } git_cred_ssh_key; /** + * Keyboard-interactive based ssh authentication + */ +typedef struct git_cred_ssh_interactive { + git_cred parent; + char *username; + git_cred_ssh_interactive_callback prompt_callback; + void *payload; +} git_cred_ssh_interactive; + +/** * A key with a custom signature function */ typedef struct git_cred_ssh_custom { @@ -83,8 +98,8 @@ typedef struct git_cred_ssh_custom { char *username; char *publickey; size_t publickey_len; - void *sign_callback; - void *sign_data; + git_cred_sign_callback sign_callback; + void *payload; } git_cred_ssh_custom; /** A key for NTLM/Kerberos "default" credentials */ @@ -131,6 +146,33 @@ GIT_EXTERN(int) git_cred_ssh_key_new( const char *passphrase); /** + * Create a new ssh keyboard-interactive based credential object. + * The supplied credential parameter will be internally duplicated. + * + * @param username Username to use to authenticate. + * @param prompt_callback The callback method used for prompts. + * @param payload Additional data to pass to the callback. + * @return 0 for success or an error code for failure. + */ +GIT_EXTERN(int) git_cred_ssh_interactive_new( + git_cred **out, + const char *username, + git_cred_ssh_interactive_callback prompt_callback, + void *payload); + +/** + * Create a new ssh key credential object used for querying an ssh-agent. + * The supplied credential parameter will be internally duplicated. + * + * @param out The newly created credential object. + * @param username username to use to authenticate + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_cred_ssh_key_from_agent( + git_cred **out, + const char *username); + +/** * Create an ssh key credential with a custom signing function. * * This lets you use your own function to sign the challenge. @@ -144,8 +186,8 @@ GIT_EXTERN(int) git_cred_ssh_key_new( * @param username username to use to authenticate * @param publickey The bytes of the public key. * @param publickey_len The length of the public key in bytes. - * @param sign_fn The callback method to sign the data during the challenge. - * @param sign_data The data to pass to the sign function. + * @param sign_callback The callback method to sign the data during the challenge. + * @param payload Additional data to pass to the callback. * @return 0 for success or an error code for failure */ GIT_EXTERN(int) git_cred_ssh_custom_new( @@ -153,8 +195,8 @@ GIT_EXTERN(int) git_cred_ssh_custom_new( const char *username, const char *publickey, size_t publickey_len, - git_cred_sign_callback sign_fn, - void *sign_data); + git_cred_sign_callback sign_callback, + void *payload); /** * Create a "default" credential usable for Negotiate mechanisms like NTLM @@ -173,7 +215,8 @@ GIT_EXTERN(int) git_cred_default_new(git_cred **out); * remote url, or NULL if not included. * - allowed_types: A bitmask stating which cred types are OK to return. * - payload: The payload provided when specifying this callback. - * - returns 0 for success or non-zero to indicate an error + * - returns 0 for success, < 0 to indicate an error, > 0 to indicate + * no credential was acquired */ typedef int (*git_cred_acquire_cb)( git_cred **cred, @@ -244,7 +287,7 @@ struct git_transport { git_transport *transport, git_repository *repo, git_transfer_progress *stats, - git_transfer_progress_callback progress_cb, + git_transfer_progress_cb progress_cb, void *progress_payload); /* Checks to see if the transport is connected */ @@ -268,6 +311,18 @@ struct git_transport { #define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION} /** + * Initializes a `git_transport` with default values. Equivalent to + * creating an instance with GIT_TRANSPORT_INIT. + * + * @param opts the `git_transport` struct to initialize + * @param version Version of struct; pass `GIT_TRANSPORT_VERSION` + * @return Zero on success; -1 on failure. + */ +GIT_EXTERN(int) git_transport_init( + git_transport *opts, + unsigned int version); + +/** * Function to use to create a transport from a URL. The transport database * is scanned to find a transport that implements the scheme of the URI (i.e. * git:// or http://) and a transport object is returned to the caller. diff --git a/include/git2/tree.h b/include/git2/tree.h index d94b446c2..56922d40b 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -121,11 +121,11 @@ GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex( * Warning: this must examine every entry in the tree, so it is not fast. * * @param tree a previously loaded tree. - * @param oid the sha being looked for + * @param id the sha being looked for * @return the tree entry; NULL if not found */ -GIT_EXTERN(const git_tree_entry *) git_tree_entry_byoid( - const git_tree *tree, const git_oid *oid); +GIT_EXTERN(const git_tree_entry *) git_tree_entry_byid( + const git_tree *tree, const git_oid *id); /** * Retrieve a tree entry contained in a tree or in any of its subtrees, @@ -150,10 +150,11 @@ GIT_EXTERN(int) git_tree_entry_bypath( * Create a copy of a tree entry. The returned copy is owned by the user, * and must be freed explicitly with `git_tree_entry_free()`. * - * @param entry A tree entry to duplicate - * @return a copy of the original entry or NULL on error (alloc failure) + * @param dest pointer where to store the copy + * @param source tree entry to duplicate + * @return 0 or an error code */ -GIT_EXTERN(git_tree_entry *) git_tree_entry_dup(const git_tree_entry *entry); +GIT_EXTERN(int) git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source); /** * Free a user-owned tree entry @@ -332,11 +333,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 +352,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, diff --git a/include/git2/types.h b/include/git2/types.h index 55505b110..6295ebbfa 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -131,7 +131,7 @@ typedef struct git_treebuilder git_treebuilder; /** Memory representation of an index file. */ typedef struct git_index git_index; -/** An interator for conflicts in the index. */ +/** An iterator for conflicts in the index. */ typedef struct git_index_conflict_iterator git_index_conflict_iterator; /** Memory representation of a set of config files */ @@ -154,15 +154,15 @@ typedef struct git_packbuilder git_packbuilder; /** Time in a signature */ typedef struct git_time { - git_time_t time; /** time in seconds from epoch */ - int offset; /** timezone offset, in minutes */ + git_time_t time; /**< time in seconds from epoch */ + int offset; /**< timezone offset, in minutes */ } git_time; /** An action signature (e.g. for committers, taggers, etc) */ typedef struct git_signature { - char *name; /** full name of the author */ - char *email; /** email of the author */ - git_time when; /** time when the action happened */ + char *name; /**< full name of the author */ + char *email; /**< email of the author */ + git_time when; /**< time when the action happened */ } git_signature; /** In-memory representation of a reference. */ @@ -183,9 +183,9 @@ typedef struct git_status_list git_status_list; /** Basic type of any Git reference. */ typedef enum { - GIT_REF_INVALID = 0, /** Invalid reference */ - GIT_REF_OID = 1, /** A reference which points at an object id */ - GIT_REF_SYMBOLIC = 2, /** A reference which points at another reference */ + GIT_REF_INVALID = 0, /**< Invalid reference */ + GIT_REF_OID = 1, /**< A reference which points at an object id */ + GIT_REF_SYMBOLIC = 2, /**< A reference which points at another reference */ GIT_REF_LISTALL = GIT_REF_OID|GIT_REF_SYMBOLIC, } git_ref_t; @@ -193,6 +193,7 @@ typedef enum { typedef enum { GIT_BRANCH_LOCAL = 1, GIT_BRANCH_REMOTE = 2, + GIT_BRANCH_ALL = GIT_BRANCH_LOCAL|GIT_BRANCH_REMOTE, } git_branch_t; /** Valid modes for index and tree entries. */ @@ -240,7 +241,7 @@ typedef struct git_transfer_progress { * @param stats Structure containing information about the state of the transfer * @param payload Payload provided by caller */ -typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload); +typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void *payload); /** * Opaque structure representing a submodule. @@ -313,16 +314,35 @@ typedef enum { * when we don't want any particular ignore rule to be specified. */ typedef enum { - GIT_SUBMODULE_IGNORE_RESET = -1, /* reset to on-disk value */ + GIT_SUBMODULE_IGNORE_RESET = -1, /**< reset to on-disk value */ - GIT_SUBMODULE_IGNORE_NONE = 1, /* any change or untracked == dirty */ - GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /* dirty if tracked files change */ - GIT_SUBMODULE_IGNORE_DIRTY = 3, /* only dirty if HEAD moved */ - GIT_SUBMODULE_IGNORE_ALL = 4, /* never dirty */ + GIT_SUBMODULE_IGNORE_NONE = 1, /**< any change or untracked == dirty */ + GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /**< dirty if tracked files change */ + GIT_SUBMODULE_IGNORE_DIRTY = 3, /**< only dirty if HEAD moved */ + GIT_SUBMODULE_IGNORE_ALL = 4, /**< never dirty */ GIT_SUBMODULE_IGNORE_DEFAULT = 0 } git_submodule_ignore_t; +/** + * Options for submodule recurse. + * + * Represent the value of `submodule.$name.fetchRecurseSubmodules` + * + * * GIT_SUBMODULE_RECURSE_RESET - reset to the on-disk value + * * GIT_SUBMODULE_RECURSE_NO - do no recurse into submodules + * * GIT_SUBMODULE_RECURSE_YES - recurse into submodules + * * GIT_SUBMODULE_RECURSE_ONDEMAND - recurse into submodules only when + * commit not already in local clone + */ +typedef enum { + GIT_SUBMODULE_RECURSE_RESET = -1, + + GIT_SUBMODULE_RECURSE_NO = 0, + GIT_SUBMODULE_RECURSE_YES = 1, + GIT_SUBMODULE_RECURSE_ONDEMAND = 2, +} git_submodule_recurse_t; + /** @} */ GIT_END_DECL diff --git a/include/git2/version.h b/include/git2/version.h index c4c5e8eb1..5bda42735 100644 --- a/include/git2/version.h +++ b/include/git2/version.h @@ -7,9 +7,11 @@ #ifndef INCLUDE_git_version_h__ #define INCLUDE_git_version_h__ -#define LIBGIT2_VERSION "0.20.0" +#define LIBGIT2_VERSION "0.21.0" #define LIBGIT2_VER_MAJOR 0 -#define LIBGIT2_VER_MINOR 20 +#define LIBGIT2_VER_MINOR 21 #define LIBGIT2_VER_REVISION 0 +#define LIBGIT2_SOVERSION 21 + #endif |
