diff --git a/git2/frameworks/libgit2.0.17.0.dylib b/git2/frameworks/libgit2.0.17.0.dylib index 1b99207a1..e51506da0 100755 Binary files a/git2/frameworks/libgit2.0.17.0.dylib and b/git2/frameworks/libgit2.0.17.0.dylib differ diff --git a/git2/include/git2.h b/git2/include/git2.h index d75387318..d55543986 100644 --- a/git2/include/git2.h +++ b/git2/include/git2.h @@ -25,6 +25,7 @@ #include "git2/merge.h" #include "git2/refs.h" #include "git2/reflog.h" +#include "git2/revparse.h" #include "git2/object.h" #include "git2/blob.h" @@ -36,12 +37,20 @@ #include "git2/index.h" #include "git2/config.h" #include "git2/remote.h" +#include "git2/clone.h" +#include "git2/checkout.h" +#include "git2/attr.h" +#include "git2/ignore.h" +#include "git2/branch.h" #include "git2/refspec.h" #include "git2/net.h" #include "git2/status.h" #include "git2/indexer.h" #include "git2/submodule.h" #include "git2/notes.h" +#include "git2/reset.h" +#include "git2/message.h" +#include "git2/pack.h" #endif diff --git a/git2/include/git2/attr.h b/git2/include/git2/attr.h index 28ca3bc1c..2de9f4b0e 100644 --- a/git2/include/git2/attr.h +++ b/git2/include/git2/attr.h @@ -30,7 +30,7 @@ GIT_BEGIN_DECL * Then for file `xyz.c` looking up attribute "foo" gives a value for * which `GIT_ATTR_TRUE(value)` is true. */ -#define GIT_ATTR_TRUE(attr) ((attr) == git_attr__true) +#define GIT_ATTR_TRUE(attr) (git_attr_value(attr) == GIT_ATTR_TRUE_T) /** * GIT_ATTR_FALSE checks if an attribute is set off. In core git @@ -44,7 +44,7 @@ GIT_BEGIN_DECL * Then for file `zyx.h` looking up attribute "foo" gives a value for * which `GIT_ATTR_FALSE(value)` is true. */ -#define GIT_ATTR_FALSE(attr) ((attr) == git_attr__false) +#define GIT_ATTR_FALSE(attr) (git_attr_value(attr) == GIT_ATTR_FALSE_T) /** * GIT_ATTR_UNSPECIFIED checks if an attribute is unspecified. This @@ -62,11 +62,11 @@ GIT_BEGIN_DECL * file `onefile.rb` or looking up "bar" on any file will all give * `GIT_ATTR_UNSPECIFIED(value)` of true. */ -#define GIT_ATTR_UNSPECIFIED(attr) (!(attr) || (attr) == git_attr__unset) +#define GIT_ATTR_UNSPECIFIED(attr) (git_attr_value(attr) == GIT_ATTR_UNSPECIFIED_T) /** * GIT_ATTR_HAS_VALUE checks if an attribute is set to a value (as - * opposied to TRUE, FALSE or UNSPECIFIED). This would be the case if + * opposed to TRUE, FALSE or UNSPECIFIED). This would be the case if * for a file with something like: * * *.txt eol=lf @@ -74,13 +74,29 @@ GIT_BEGIN_DECL * Given this, looking up "eol" for `onefile.txt` will give back the * string "lf" and `GIT_ATTR_SET_TO_VALUE(attr)` will return true. */ -#define GIT_ATTR_HAS_VALUE(attr) \ - ((attr) && (attr) != git_attr__unset && \ - (attr) != git_attr__true && (attr) != git_attr__false) +#define GIT_ATTR_HAS_VALUE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_T) -GIT_EXTERN(const char *) git_attr__true; -GIT_EXTERN(const char *) git_attr__false; -GIT_EXTERN(const char *) git_attr__unset; +typedef enum { + GIT_ATTR_UNSPECIFIED_T = 0, + GIT_ATTR_TRUE_T, + GIT_ATTR_FALSE_T, + GIT_ATTR_VALUE_T, +} git_attr_t; + +/* + * Return the value type for a given attribute. + * + * This can be either `TRUE`, `FALSE`, `UNSPECIFIED` (if the attribute + * was not set at all), or `VALUE`, if the attribute was set to + * an actual string. + * + * If the attribute has a `VALUE` string, it can be accessed normally + * as a NULL-terminated C string. + * + * @param attr The attribute + * @return the value type for the attribute + */ +GIT_EXTERN(git_attr_t) git_attr_value(const char *attr); /** * Check attribute flags: Reading values from index and working directory. @@ -172,18 +188,17 @@ GIT_EXTERN(int) git_attr_get_many( * * @param repo The repository containing the path. * @param flags A combination of GIT_ATTR_CHECK... flags. - * @param path The path inside the repo to check attributes. This - * does not have to exist, but if it does not, then - * it will be treated as a plain file (i.e. not a directory). - * @param callback The function that will be invoked on each attribute - * and attribute value. The name parameter will be the name - * of the attribute and the value will be the value it is - * set to, including possibly NULL if the attribute is - * explicitly set to UNSPECIFIED using the ! sign. This - * will be invoked only once per attribute name, even if - * there are multiple rules for a given file. The highest - * priority rule will be used. + * @param path Path inside the repo to check attributes. This does not have + * to exist, but if it does not, then it will be treated as a + * plain file (i.e. not a directory). + * @param callback Function to invoke on each attribute name and value. The + * value may be NULL is the attribute is explicitly set to + * UNSPECIFIED using the '!' sign. Callback will be invoked + * only once per attribute name, even if there are multiple + * rules for a given file. The highest priority rule will be + * used. Return a non-zero value from this to stop looping. * @param payload Passed on as extra parameter to callback function. + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_attr_foreach( git_repository *repo, diff --git a/git2/include/git2/blob.h b/git2/include/git2/blob.h index 551770678..f0719f15d 100644 --- a/git2/include/git2/blob.h +++ b/git2/include/git2/blob.h @@ -46,7 +46,7 @@ GIT_INLINE(int) git_blob_lookup(git_blob **blob, git_repository *repo, const git * @param len the length of the short identifier * @return 0 or an error code */ -GIT_INLINE(int) git_blob_lookup_prefix(git_blob **blob, git_repository *repo, const git_oid *id, unsigned int len) +GIT_INLINE(int) git_blob_lookup_prefix(git_blob **blob, git_repository *repo, const git_oid *id, size_t len) { return git_object_lookup_prefix((git_object **)blob, repo, id, len, GIT_OBJ_BLOB); } @@ -115,6 +115,48 @@ GIT_EXTERN(int) git_blob_create_fromfile(git_oid *oid, git_repository *repo, con */ GIT_EXTERN(int) git_blob_create_fromdisk(git_oid *oid, git_repository *repo, const char *path); +/** + * 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. + * + * + * The implementation of the callback has to respect the + * following rules: + * + * - `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 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. + * + * + * @param oid 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 GIT_SUCCESS or an error code + */ +GIT_EXTERN(int) git_blob_create_fromchunks( + git_oid *oid, + git_repository *repo, + const char *hintpath, + int (*source_cb)(char *content, size_t max_length, void *payload), + void *payload); /** * Write an in-memory buffer to the ODB as a blob diff --git a/git2/include/git2/branch.h b/git2/include/git2/branch.h index e2432bcfc..f06609a51 100644 --- a/git2/include/git2/branch.h +++ b/git2/include/git2/branch.h @@ -8,6 +8,7 @@ #define INCLUDE_git_branch_h__ #include "common.h" +#include "oid.h" #include "types.h" /** @@ -26,9 +27,9 @@ GIT_BEGIN_DECL * this target commit. If `force` is true and a reference * already exists with the given name, it'll be replaced. * - * @param oid_out Pointer where to store the OID of the target commit. + * The returned reference must be freed by the user. * - * @param repo Repository where to store the branch. + * @param branch_out Pointer where to store the underlying reference. * * @param branch_name Name for the branch; this name is * validated for consistency. It should also not conflict with @@ -46,7 +47,7 @@ GIT_BEGIN_DECL * pointing to the provided target commit. */ GIT_EXTERN(int) git_branch_create( - git_oid *oid_out, + git_reference **branch_out, git_repository *repo, const char *branch_name, const git_object *target, @@ -55,32 +56,18 @@ GIT_EXTERN(int) git_branch_create( /** * Delete an existing branch reference. * - * @param repo Repository where lives the branch. + * If the branch is successfully deleted, the passed reference + * object will be freed and invalidated. * - * @param branch_name Name of the branch to be deleted; - * this name is validated for consistency. - * - * @param branch_type Type of the considered branch. This should - * be valued with either GIT_BRANCH_LOCAL or GIT_BRANCH_REMOTE. - * - * @return 0 on success, GIT_ENOTFOUND if the branch - * doesn't exist or an error code. + * @param branch A valid reference representing a branch + * @return 0 on success, or an error code. */ -GIT_EXTERN(int) git_branch_delete( - git_repository *repo, - const char *branch_name, - git_branch_t branch_type); +GIT_EXTERN(int) git_branch_delete(git_reference *branch); /** - * Fill a list with all the branches in the Repository + * Loop over all the branches and issue a callback for each one. * - * The string array will be filled with the names of the - * matching branches; these values are owned by the user and - * should be free'd manually when no longer needed, using - * `git_strarray_free`. - * - * @param branch_names Pointer to a git_strarray structure - * where the branch names will be stored. + * If the callback returns a non-zero value, this will stop looping. * * @param repo Repository where to find the branches. * @@ -88,35 +75,90 @@ GIT_EXTERN(int) git_branch_delete( * listing. Valid values are GIT_BRANCH_LOCAL, GIT_BRANCH_REMOTE * or a combination of the two. * - * @return 0 or an error code. + * @param branch_cb Callback to invoke per found branch. + * + * @param payload Extra parameter to callback function. + * + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ -GIT_EXTERN(int) git_branch_list( - git_strarray *branch_names, +GIT_EXTERN(int) git_branch_foreach( git_repository *repo, - unsigned int list_flags); + unsigned int list_flags, + int (*branch_cb)( + const char *branch_name, + git_branch_t branch_type, + void *payload), + void *payload +); /** - * Move/rename an existing branch reference. + * Move/rename an existing local branch reference. * - * @param repo Repository where lives the branch. - * - * @param old_branch_name Current name of the branch to be moved; - * this name is validated for consistency. + * @param branch Current underlying reference of the branch. * * @param new_branch_name Target name of the branch once the move * is performed; this name is validated for consistency. * * @param force Overwrite existing branch. * - * @return 0 on success, GIT_ENOTFOUND if the branch - * doesn't exist or an error code. + * @return 0 on success, or an error code. */ GIT_EXTERN(int) git_branch_move( - git_repository *repo, - const char *old_branch_name, + git_reference *branch, const char *new_branch_name, int force); +/** + * Lookup a branch by its name in a repository. + * + * The generated reference must be freed by the user. + * + * @param branch_out pointer to the looked-up branch reference + * + * @param repo the repository to look up the branch + * + * @param branch_name Name of the branch to be looked-up; + * this name is validated for consistency. + * + * @param branch_type Type of the considered branch. This should + * be valued with either GIT_BRANCH_LOCAL or GIT_BRANCH_REMOTE. + * + * @return 0 on success; GIT_ENOTFOUND when no matching branch + * exists, otherwise an error code. + */ +GIT_EXTERN(int) git_branch_lookup( + git_reference **branch_out, + git_repository *repo, + const char *branch_name, + git_branch_t branch_type); + +/** + * Return the reference supporting the remote tracking branch, + * given a local branch reference. + * + * @param tracking_out Pointer where to store the retrieved + * reference. + * + * @param branch Current underlying reference of the branch. + * + * @return 0 on success; GIT_ENOTFOUND when no remote tracking + * reference exists, otherwise an error code. + */ +GIT_EXTERN(int) git_branch_tracking( + git_reference **tracking_out, + git_reference *branch); + +/** + * Determine if the current local branch is pointed at by HEAD. + * + * @param branch Current underlying reference of the branch. + * + * @return 1 if HEAD points at the branch, 0 if it isn't, + * error code otherwise. + */ +GIT_EXTERN(int) git_branch_is_head( + git_reference *branch); + /** @} */ GIT_END_DECL #endif diff --git a/git2/include/git2/checkout.h b/git2/include/git2/checkout.h new file mode 100644 index 000000000..390d2f215 --- /dev/null +++ b/git2/include/git2/checkout.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2012 the libgit2 contributors + * + * 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_checkout_h__ +#define INCLUDE_git_checkout_h__ + +#include "common.h" +#include "types.h" +#include "indexer.h" +#include "strarray.h" + +/** + * @file git2/checkout.h + * @brief Git checkout routines + * @defgroup git_checkout Git checkout routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Checkout behavior flags + * + * These flags control what checkout does with files. Pass in a + * combination of these values OR'ed together. + */ +typedef enum { + /** Checkout does not update any files in the working directory. */ + GIT_CHECKOUT_DEFAULT = (1 << 0), + + /** When a file exists and is modified, replace it with new version. */ + GIT_CHECKOUT_OVERWRITE_MODIFIED = (1 << 1), + + /** When a file does not exist in the working directory, create it. */ + GIT_CHECKOUT_CREATE_MISSING = (1 << 2), + + /** If an untracked file in found in the working dir, delete it. */ + GIT_CHECKOUT_REMOVE_UNTRACKED = (1 << 3), +} git_checkout_strategy_t; + +/** + * Checkout options structure + * + * Use zeros to indicate default settings. + */ +typedef struct git_checkout_opts { + unsigned int checkout_strategy; /** default: GIT_CHECKOUT_DEFAULT */ + int disable_filters; /** don't apply filters like CRLF conversion */ + int dir_mode; /** default is 0755 */ + int file_mode; /** default is 0644 or 0755 as dictated by blob */ + int file_open_flags; /** default is O_CREAT | O_TRUNC | O_WRONLY */ + + /** Optional callback to notify the consumer of files that + * haven't be checked out because a modified version of them + * exist in the working directory. + * + * When provided, this callback will be invoked when the flag + * GIT_CHECKOUT_OVERWRITE_MODIFIED isn't part of the checkout strategy. + */ + int (* skipped_notify_cb)( + const char *skipped_file, + const git_oid *blob_oid, + int file_mode, + void *payload); + void *notify_payload; + + /* Optional callback to notify the consumer of checkout progress. */ + void (* progress_cb)( + const char *path, + size_t completed_steps, + size_t total_steps, + void *payload); + void *progress_payload; + + /** When not NULL, array of fnmatch patterns specifying + * which paths should be taken into account + */ + git_strarray paths; +} git_checkout_opts; + +/** + * Updates files in the index and the working tree to match the content of the + * commit pointed at by HEAD. + * + * @param repo repository to check out (must be non-bare) + * @param opts specifies checkout options (may be NULL) + * @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing + * branch, GIT_ERROR otherwise (use giterr_last for information + * about the error) + */ +GIT_EXTERN(int) git_checkout_head( + git_repository *repo, + git_checkout_opts *opts); + +/** + * Updates files in the working tree to match the content of the index. + * + * @param repo repository to check out (must be non-bare) + * @param opts specifies checkout options (may be NULL) + * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information + * about the error) + */ +GIT_EXTERN(int) git_checkout_index( + git_repository *repo, + git_checkout_opts *opts); + +/** + * Updates files in the index and working tree to match the content of the + * tree pointed at by the treeish. + * + * @param repo repository to check out (must be non-bare) + * @param treeish a commit, tag or tree which content will be used to update + * the working directory + * @param opts specifies checkout options (may be NULL) + * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information + * about the error) + */ +GIT_EXTERN(int) git_checkout_tree( + git_repository *repo, + git_object *treeish, + git_checkout_opts *opts); + +/** @} */ +GIT_END_DECL +#endif diff --git a/git2/include/git2/clone.h b/git2/include/git2/clone.h new file mode 100644 index 000000000..7d8d32118 --- /dev/null +++ b/git2/include/git2/clone.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 the libgit2 contributors + * + * 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_clone_h__ +#define INCLUDE_git_clone_h__ + +#include "common.h" +#include "types.h" +#include "indexer.h" +#include "checkout.h" + + +/** + * @file git2/clone.h + * @brief Git cloning routines + * @defgroup git_clone Git cloning routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Clone a remote repository, and checkout the branch pointed to by the remote + * HEAD. + * + * @param out pointer that will receive the resulting repository object + * @param origin_url repository to clone from + * @param workdir_path local directory to clone to + * @param fetch_progress_cb optional callback for fetch progress. Be aware that + * this is called inline with network and indexing operations, so performance + * may be affected. + * @param fetch_progress_payload payload for fetch_progress_cb + * @param checkout_opts options for the checkout step. If NULL, no checkout + * is performed + * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information + * about the error) + */ +GIT_EXTERN(int) git_clone( + git_repository **out, + const char *origin_url, + const char *workdir_path, + git_transfer_progress_callback fetch_progress_cb, + void *fetch_progress_payload, + git_checkout_opts *checkout_opts); + +/** + * Create a bare clone of a remote repository. + * + * @param out pointer that will receive the resulting repository object + * @param origin_url repository to clone from + * @param dest_path local directory to clone to + * @param fetch_progress_cb optional callback for fetch progress. Be aware that + * this is called inline with network and indexing operations, so performance + * may be affected. + * @param fetch_progress_payload payload for fetch_progress_cb + * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information about the error) + */ +GIT_EXTERN(int) git_clone_bare( + git_repository **out, + const char *origin_url, + const char *dest_path, + git_transfer_progress_callback fetch_progress_cb, + void *fetch_progress_payload); + +/** @} */ +GIT_END_DECL +#endif diff --git a/git2/include/git2/commit.h b/git2/include/git2/commit.h index a6d9bb0e3..a159b79e1 100644 --- a/git2/include/git2/commit.h +++ b/git2/include/git2/commit.h @@ -48,7 +48,7 @@ GIT_INLINE(int) git_commit_lookup(git_commit **commit, git_repository *repo, con * @param len the length of the short identifier * @return 0 or an error code */ -GIT_INLINE(int) git_commit_lookup_prefix(git_commit **commit, git_repository *repo, const git_oid *id, unsigned len) +GIT_INLINE(int) git_commit_lookup_prefix(git_commit **commit, git_repository *repo, const git_oid *id, size_t len) { return git_object_lookup_prefix((git_object **)commit, repo, id, len, GIT_OBJ_COMMIT); } @@ -178,12 +178,31 @@ GIT_EXTERN(int) git_commit_parent(git_commit **parent, git_commit *commit, unsig */ GIT_EXTERN(const git_oid *) git_commit_parent_oid(git_commit *commit, unsigned int n); +/** + * Get the commit object that is the th generation ancestor + * of the named commit object, following only the first parents. + * The returned commit has to be freed by the caller. + * + * Passing `0` as the generation number returns another instance of the + * base commit itself. + * + * @param ancestor Pointer where to store the ancestor commit + * @param commit a previously loaded commit. + * @param n the requested generation + * @return 0 on success; GIT_ENOTFOUND if no matching ancestor exists + * or an error code + */ +GIT_EXTERN(int) git_commit_nth_gen_ancestor( + git_commit **ancestor, + const git_commit *commit, + unsigned int n); + /** * Create a new commit in the repository using `git_object` * instances as parameters. * - * The message will be cleaned up from excess whitespace - * it will be made sure that the last line ends with a '\n'. + * The message will not be cleaned up. This can be achieved + * through `git_message_prettify()`. * * @param oid Pointer where to store the OID of the * newly created commit diff --git a/git2/include/git2/common.h b/git2/include/git2/common.h index 0e9379804..dd6909f90 100644 --- a/git2/include/git2/common.h +++ b/git2/include/git2/common.h @@ -55,6 +55,10 @@ #define GIT_WIN32 1 #endif +#ifdef __amigaos4__ +#include +#endif + /** * @file git2/common.h * @brief Git common platform definitions @@ -81,14 +85,6 @@ GIT_BEGIN_DECL */ #define GIT_PATH_MAX 4096 -typedef struct { - char **strings; - size_t count; -} git_strarray; - -GIT_EXTERN(void) git_strarray_free(git_strarray *array); -GIT_EXTERN(int) git_strarray_copy(git_strarray *tgt, const git_strarray *src); - /** * Return the version of the libgit2 library * being currently used. @@ -99,6 +95,30 @@ GIT_EXTERN(int) git_strarray_copy(git_strarray *tgt, const git_strarray *src); */ GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev); +/** + * Combinations of these values describe the capabilities of libgit2. + */ +enum { + GIT_CAP_THREADS = ( 1 << 0 ), + GIT_CAP_HTTPS = ( 1 << 1 ) +}; + +/** + * Query compile time options for libgit2. + * + * @return A combination of GIT_CAP_* values. + * + * - GIT_CAP_THREADS + * Libgit2 was compiled with thread support. Note that thread support is still to be seen as a + * 'work in progress'. + * + * - GIT_CAP_HTTPS + * Libgit2 supports the https:// protocol. This requires the open ssl library to be + * found when compiling libgit2. + */ +GIT_EXTERN(int) git_libgit2_capabilities(void); + /** @} */ GIT_END_DECL + #endif diff --git a/git2/include/git2/config.h b/git2/include/git2/config.h index 36946c4a5..67408f90f 100644 --- a/git2/include/git2/config.h +++ b/git2/include/git2/config.h @@ -19,6 +19,28 @@ */ GIT_BEGIN_DECL +/** + * Priority level of a config file. + * These priority levels correspond to the natural escalation logic + * (from higher to lower) when searching for config entries in git.git. + * + * git_config_open_default() and git_repository_config() honor those + * priority levels as well. + */ +enum { + GIT_CONFIG_LEVEL_SYSTEM = 1, /**< System-wide configuration file. */ + GIT_CONFIG_LEVEL_XDG = 2, /**< XDG compatible configuration file (.config/git/config). */ + GIT_CONFIG_LEVEL_GLOBAL = 3, /**< User-specific configuration file, also called Global configuration file. */ + GIT_CONFIG_LEVEL_LOCAL = 4, /**< Repository specific configuration file. */ + GIT_CONFIG_HIGHEST_LEVEL = -1, /**< Represents the highest level of a config file. */ +}; + +typedef struct { + const char *name; + const char *value; + unsigned int level; +} git_config_entry; + /** * Generic backend that implements the interface to * access a configuration file @@ -27,13 +49,13 @@ struct git_config_file { struct git_config *cfg; /* Open means open the file/database and parse if necessary */ - int (*open)(struct git_config_file *); - int (*get)(struct git_config_file *, const char *key, const char **value); - int (*get_multivar)(struct git_config_file *, const char *key, const char *regexp, int (*fn)(const char *, void *), void *data); + int (*open)(struct git_config_file *, unsigned int level); + int (*get)(struct git_config_file *, const char *key, const git_config_entry **entry); + int (*get_multivar)(struct git_config_file *, const char *key, const char *regexp, int (*fn)(const git_config_entry *, void *), void *data); int (*set)(struct git_config_file *, const char *key, const char *value); int (*set_multivar)(git_config_file *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_file *, const char *key); - int (*foreach)(struct git_config_file *, int (*fn)(const char *, const char *, void *), void *data); + int (*foreach)(struct git_config_file *, const char *, int (*fn)(const git_config_entry *, void *), void *data); void (*free)(struct git_config_file *); }; @@ -61,12 +83,32 @@ typedef struct { * may be used on any `git_config` call to load the * global configuration file. * + * This method will not guess the path to the xdg compatible + * config file (.config/git/config). + * * @param global_config_path Buffer of GIT_PATH_MAX length to store the path * @return 0 if a global configuration file has been * found. Its path will be stored in `buffer`. */ GIT_EXTERN(int) git_config_find_global(char *global_config_path, size_t length); +/** + * Locate the path to the global xdg compatible configuration file + * + * The xdg compatible configuration file is usually + * located in `$HOME/.config/git/config`. + * + * This method will try to guess the full path to that + * file, if the file exists. The returned path + * may be used on any `git_config` call to load the + * xdg compatible configuration file. + * + * @param xdg_config_path Buffer of GIT_PATH_MAX length to store the path + * @return 0 if a xdg compatible configuration file has been + * found. Its path will be stored in `buffer`. + */ +GIT_EXTERN(int) git_config_find_xdg(char *xdg_config_path, size_t length); + /** * Locate the path to the system configuration file * @@ -80,15 +122,16 @@ GIT_EXTERN(int) git_config_find_global(char *global_config_path, size_t length); GIT_EXTERN(int) git_config_find_system(char *system_config_path, size_t length); /** - * Open the global configuration file + * Open the global, XDG and system configuration files * - * Utility wrapper that calls `git_config_find_global` - * and opens the located file, if it exists. + * Utility wrapper that finds the global, XDG and system configuration files + * and opens them into a single prioritized config object that can be + * used when accessing default config data outside a repository. * * @param out Pointer to store the config instance * @return 0 or an error code */ -GIT_EXTERN(int) git_config_open_global(git_config **out); +GIT_EXTERN(int) git_config_open_default(git_config **out); /** * Create a configuration file backend for ondisk files @@ -122,14 +165,21 @@ GIT_EXTERN(int) git_config_new(git_config **out); * * Further queries on this config object will access each * of the config file instances in order (instances with - * a higher priority will be accessed first). + * a higher priority level will be accessed first). * * @param cfg the configuration to add the file to * @param file the configuration file (backend) to add - * @param priority the priority the backend should have - * @return 0 or an error code + * @param level the priority level of the backend + * @param force if a config file already exists for the given + * priority level, replace it + * @return 0 on success, GIT_EEXISTS when adding more than one file + * for a given priority level (and force_replace set to 0), or error code */ -GIT_EXTERN(int) git_config_add_file(git_config *cfg, git_config_file *file, int priority); +GIT_EXTERN(int) git_config_add_file( + git_config *cfg, + git_config_file *file, + unsigned int level, + int force); /** * Add an on-disk config file instance to an existing config @@ -143,14 +193,21 @@ GIT_EXTERN(int) git_config_add_file(git_config *cfg, git_config_file *file, int * * Further queries on this config object will access each * of the config file instances in order (instances with - * a higher priority will be accessed first). + * a higher priority level will be accessed first). * * @param cfg the configuration to add the file to * @param path path to the configuration file (backend) to add - * @param priority the priority the backend should have - * @return 0 or an error code + * @param level the priority level of the backend + * @param force if a config file already exists for the given + * priority level, replace it + * @return 0 on success, GIT_EEXISTS when adding more than one file + * for a given priority level (and force_replace set to 0), or error code */ -GIT_EXTERN(int) git_config_add_file_ondisk(git_config *cfg, const char *path, int priority); +GIT_EXTERN(int) git_config_add_file_ondisk( + git_config *cfg, + const char *path, + unsigned int level, + int force); /** @@ -167,6 +224,24 @@ GIT_EXTERN(int) git_config_add_file_ondisk(git_config *cfg, const char *path, in */ GIT_EXTERN(int) git_config_open_ondisk(git_config **cfg, const char *path); +/** + * Build a single-level focused config object from a multi-level one. + * + * The returned config object can be used to perform get/set/delete operations + * on a single specific level. + * + * Getting several times the same level from the same parent multi-level config + * will return different config instances, but containing the same config_file + * instance. + * + * @return 0, GIT_ENOTFOUND if the passed level cannot be found in the + * multi-level parent config, or an error code + */ +GIT_EXTERN(int) git_config_open_level( + git_config **cfg_out, + git_config *cfg_parent, + unsigned int level); + /** * Free the configuration and its associated memory and files * @@ -174,9 +249,26 @@ GIT_EXTERN(int) git_config_open_ondisk(git_config **cfg, const char *path); */ GIT_EXTERN(void) git_config_free(git_config *cfg); +/** + * Get the git_config_entry of a config variable. + * + * The git_config_entry is owned by the config and should not be freed by the + * user. + + * @param out pointer to the variable git_config_entry + * @param cfg where to look for the variable + * @param name the variable's name + * @return 0 or an error code + */ +GIT_EXTERN(int) git_config_get_config_entry(const git_config_entry **out, git_config *cfg, const char *name); + /** * Get the value of an integer config variable. * + * All config files will be looked into, in the order of their + * defined level. A higher level means a higher priority. The + * first occurence of the variable will be returned here. + * * @param out pointer to the variable where the value should be stored * @param cfg where to look for the variable * @param name the variable's name @@ -187,6 +279,10 @@ GIT_EXTERN(int) git_config_get_int32(int32_t *out, git_config *cfg, const char * /** * Get the value of a long integer config variable. * + * All config files will be looked into, in the order of their + * defined level. A higher level means a higher priority. The + * first occurence of the variable will be returned here. + * * @param out pointer to the variable where the value should be stored * @param cfg where to look for the variable * @param name the variable's name @@ -200,6 +296,10 @@ GIT_EXTERN(int) git_config_get_int64(int64_t *out, git_config *cfg, const char * * This function uses the usual C convention of 0 being false and * anything else true. * + * All config files will be looked into, in the order of their + * defined level. A higher level means a higher priority. The + * first occurence of the variable will be returned here. + * * @param out pointer to the variable where the value should be stored * @param cfg where to look for the variable * @param name the variable's name @@ -213,6 +313,10 @@ GIT_EXTERN(int) git_config_get_bool(int *out, git_config *cfg, const char *name) * The string is owned by the variable and should not be freed by the * user. * + * All config files will be looked into, in the order of their + * defined level. A higher level means a higher priority. The + * first occurence of the variable will be returned here. + * * @param out pointer to the variable's value * @param cfg where to look for the variable * @param name the variable's name @@ -232,10 +336,11 @@ GIT_EXTERN(int) git_config_get_string(const char **out, git_config *cfg, const c * @param fn the function to be called on each value of the variable * @param data opaque pointer to pass to the callback */ -GIT_EXTERN(int) git_config_get_multivar(git_config *cfg, const char *name, const char *regexp, int (*fn)(const char *, void *), void *data); +GIT_EXTERN(int) git_config_get_multivar(git_config *cfg, const char *name, const char *regexp, int (*fn)(const git_config_entry *, void *), void *data); /** - * Set the value of an integer config variable. + * Set the value of an integer config variable in the config file + * with the highest level (usually the local one). * * @param cfg where to look for the variable * @param name the variable's name @@ -245,7 +350,8 @@ GIT_EXTERN(int) git_config_get_multivar(git_config *cfg, const char *name, const GIT_EXTERN(int) git_config_set_int32(git_config *cfg, const char *name, int32_t value); /** - * Set the value of a long integer config variable. + * Set the value of a long integer config variable in the config file + * with the highest level (usually the local one). * * @param cfg where to look for the variable * @param name the variable's name @@ -255,7 +361,8 @@ GIT_EXTERN(int) git_config_set_int32(git_config *cfg, const char *name, int32_t GIT_EXTERN(int) git_config_set_int64(git_config *cfg, const char *name, int64_t value); /** - * Set the value of a boolean config variable. + * Set the value of a boolean config variable in the config file + * with the highest level (usually the local one). * * @param cfg where to look for the variable * @param name the variable's name @@ -265,7 +372,8 @@ GIT_EXTERN(int) git_config_set_int64(git_config *cfg, const char *name, int64_t GIT_EXTERN(int) git_config_set_bool(git_config *cfg, const char *name, int value); /** - * Set the value of a string config variable. + * Set the value of a string config variable in the config file + * with the highest level (usually the local one). * * A copy of the string is made and the user is free to use it * afterwards. @@ -277,9 +385,8 @@ GIT_EXTERN(int) git_config_set_bool(git_config *cfg, const char *name, int value */ GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const char *value); - /** - * Set a multivar + * Set a multivar in the local config file. * * @param cfg where to look for the variable * @param name the variable's name @@ -289,7 +396,8 @@ GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const c GIT_EXTERN(int) git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value); /** - * Delete a config variable + * Delete a config variable from the config file + * with the highest level (usually the local one). * * @param cfg the configuration * @param name the variable to delete @@ -302,18 +410,36 @@ GIT_EXTERN(int) git_config_delete(git_config *cfg, const char *name); * The callback receives the normalized name and value of each variable * in the config backend, and the data pointer passed to this function. * As soon as one of the callback functions returns something other than 0, - * this function returns that value. + * this function stops iterating and returns `GIT_EUSER`. * * @param cfg where to get the variables from * @param callback the function to call on each variable * @param payload the data to pass to the callback - * @return 0 or the return value of the callback which didn't return 0 + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_config_foreach( git_config *cfg, - int (*callback)(const char *var_name, const char *value, void *payload), + int (*callback)(const git_config_entry *, void *payload), void *payload); +/** + * Perform an operation on each config variable matching a regular expression. + * + * This behaviors like `git_config_foreach` with an additional filter of a + * regular expression that filters which config keys are passed to the + * callback. + * + * @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 + * @param payload the data to pass to the callback + * @return 0 or the return value of the callback which didn't return 0 + */ +GIT_EXTERN(int) git_config_foreach_match( + git_config *cfg, + const char *regexp, + int (*callback)(const git_config_entry *entry, void *payload), + void *payload); /** * Query the value of a config variable and return it mapped to @@ -324,7 +450,7 @@ GIT_EXTERN(int) git_config_foreach( * * A mapping array looks as follows: * - * git_cvar_map autocrlf_mapping[3] = { + * git_cvar_map autocrlf_mapping[] = { * {GIT_CVAR_FALSE, NULL, GIT_AUTO_CRLF_FALSE}, * {GIT_CVAR_TRUE, NULL, GIT_AUTO_CRLF_TRUE}, * {GIT_CVAR_STRING, "input", GIT_AUTO_CRLF_INPUT}, @@ -351,6 +477,57 @@ GIT_EXTERN(int) git_config_foreach( */ GIT_EXTERN(int) git_config_get_mapped(int *out, git_config *cfg, const char *name, git_cvar_map *maps, size_t map_n); +/** + * Maps a string value to an integer constant + * + * @param out place to store the result of the parsing + * @param maps array of `git_cvar_map` objects specifying the possible mappings + * @param map_n number of mapping objects in `maps` + * @param value value to parse + */ +GIT_EXTERN(int) git_config_lookup_map_value( + int *out, + git_cvar_map *maps, + size_t map_n, + const char *value); + +/** + * Parse a string value as a bool. + * + * Valid values for true are: 'true', 'yes', 'on', 1 or any + * number different from 0 + * Valid values for false are: 'false', 'no', 'off', 0 + * + * @param out place to store the result of the parsing + * @param value value to parse + */ +GIT_EXTERN(int) git_config_parse_bool(int *out, const char *value); + +/** + * Parse a string value as an int64. + * + * An optional value suffix of 'k', 'm', or 'g' will + * cause the value to be multiplied by 1024, 1048576, + * or 1073741824 prior to output. + * + * @param out place to store the result of the parsing + * @param value value to parse + */ +GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value); + +/** + * Parse a string value as an int32. + * + * An optional value suffix of 'k', 'm', or 'g' will + * cause the value to be multiplied by 1024, 1048576, + * or 1073741824 prior to output. + * + * @param out place to store the result of the parsing + * @param value value to parse + */ +GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value); + + /** @} */ GIT_END_DECL #endif diff --git a/git2/include/git2/diff.h b/git2/include/git2/diff.h index bafe6268c..1932db029 100644 --- a/git2/include/git2/diff.h +++ b/git2/include/git2/diff.h @@ -29,19 +29,63 @@ */ GIT_BEGIN_DECL +/** + * Flags for diff options. A combination of these flags can be passed + * in via the `flags` value in the `git_diff_options`. + */ enum { + /** Normal diff, the default */ GIT_DIFF_NORMAL = 0, + /** Reverse the sides of the diff */ GIT_DIFF_REVERSE = (1 << 0), + /** Treat all files as text, disabling binary attributes & detection */ GIT_DIFF_FORCE_TEXT = (1 << 1), + /** Ignore all whitespace */ GIT_DIFF_IGNORE_WHITESPACE = (1 << 2), + /** Ignore changes in amount of whitespace */ GIT_DIFF_IGNORE_WHITESPACE_CHANGE = (1 << 3), + /** Ignore whitespace at end of line */ GIT_DIFF_IGNORE_WHITESPACE_EOL = (1 << 4), + /** Exclude submodules from the diff completely */ GIT_DIFF_IGNORE_SUBMODULES = (1 << 5), + /** Use the "patience diff" algorithm (currently unimplemented) */ GIT_DIFF_PATIENCE = (1 << 6), + /** Include ignored files in the diff list */ GIT_DIFF_INCLUDE_IGNORED = (1 << 7), + /** Include untracked files in the diff list */ GIT_DIFF_INCLUDE_UNTRACKED = (1 << 8), + /** Include unmodified files in the diff list */ GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 9), + /** Even with the GIT_DIFF_INCLUDE_UNTRACKED flag, when an untracked + * directory is found, only a single entry for the directory is added + * to the diff list; with this flag, all files under the directory will + * be included, too. + */ GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 10), + /** If the pathspec is set in the diff options, this flags means to + * apply it as an exact match instead of as an fnmatch pattern. + */ + GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1 << 11), + /** Use case insensitive filename comparisons */ + GIT_DIFF_DELTAS_ARE_ICASE = (1 << 12), + /** When generating patch text, include the content of untracked files */ + GIT_DIFF_INCLUDE_UNTRACKED_CONTENT = (1 << 13), + /** Disable updating of the `binary` flag in delta records. This is + * useful when iterating over a diff if you don't need hunk and data + * callbacks and want to avoid having to load file completely. + */ + GIT_DIFF_SKIP_BINARY_CHECK = (1 << 14), + /** Normally, a type change between files will be converted into a + * DELETED record for the old and an ADDED record for the new; this + * options enabled the generation of TYPECHANGE delta records. + */ + GIT_DIFF_INCLUDE_TYPECHANGE = (1 << 15), + /** Even with GIT_DIFF_INCLUDE_TYPECHANGE, blob->tree changes still + * generally show as a DELETED blob. This flag tries to correctly + * label blob->tree transitions as TYPECHANGE records with new_file's + * mode set to tree. Note: the tree SHA will not be available. + */ + GIT_DIFF_INCLUDE_TYPECHANGE_TREES = (1 << 16), }; /** @@ -51,15 +95,22 @@ enum { * values. Similarly, passing NULL for the options structure will * give the defaults. The default values are marked below. * - * @todo Most of the parameters here are not actually supported at this time. + * - flags: a combination of the GIT_DIFF_... values above + * - context_lines: number of lines of context to show around diffs + * - interhunk_lines: min lines between diff hunks to merge them + * - old_prefix: "directory" to prefix to old file names (default "a") + * - new_prefix: "directory" to prefix to new file names (default "b") + * - pathspec: array of paths / patterns to constrain diff + * - max_size: maximum blob size to diff, above this treated as binary */ typedef struct { uint32_t flags; /**< defaults to GIT_DIFF_NORMAL */ uint16_t context_lines; /**< defaults to 3 */ - uint16_t interhunk_lines; /**< defaults to 3 */ + uint16_t interhunk_lines; /**< defaults to 0 */ char *old_prefix; /**< defaults to "a" */ char *new_prefix; /**< defaults to "b" */ git_strarray pathspec; /**< defaults to show all paths */ + git_off_t max_size; /**< defaults to 512Mb */ } git_diff_options; /** @@ -67,13 +118,20 @@ typedef struct { */ typedef struct git_diff_list git_diff_list; +/** + * Flags that can be set for the file on side of a diff. + * + * Most of the flags are just for internal consumption by libgit2, + * but some of them may be interesting to external users. + */ enum { - GIT_DIFF_FILE_VALID_OID = (1 << 0), - GIT_DIFF_FILE_FREE_PATH = (1 << 1), - GIT_DIFF_FILE_BINARY = (1 << 2), - GIT_DIFF_FILE_NOT_BINARY = (1 << 3), - GIT_DIFF_FILE_FREE_DATA = (1 << 4), - GIT_DIFF_FILE_UNMAP_DATA = (1 << 5) + GIT_DIFF_FILE_VALID_OID = (1 << 0), /** `oid` value is known correct */ + GIT_DIFF_FILE_FREE_PATH = (1 << 1), /** `path` is allocated memory */ + GIT_DIFF_FILE_BINARY = (1 << 2), /** should be considered binary data */ + GIT_DIFF_FILE_NOT_BINARY = (1 << 3), /** should be considered text data */ + GIT_DIFF_FILE_FREE_DATA = (1 << 4), /** internal file data is allocated */ + GIT_DIFF_FILE_UNMAP_DATA = (1 << 5), /** internal file data is mmap'ed */ + GIT_DIFF_FILE_NO_DATA = (1 << 6), /** file data should not be loaded */ }; /** @@ -87,7 +145,8 @@ typedef enum { GIT_DELTA_RENAMED = 4, GIT_DELTA_COPIED = 5, GIT_DELTA_IGNORED = 6, - GIT_DELTA_UNTRACKED = 7 + GIT_DELTA_UNTRACKED = 7, + GIT_DELTA_TYPECHANGE = 8, } git_delta_t; /** @@ -95,10 +154,10 @@ typedef enum { */ typedef struct { git_oid oid; - char *path; - uint16_t mode; + const char *path; git_off_t size; unsigned int flags; + uint16_t mode; } git_diff_file; /** @@ -127,7 +186,7 @@ typedef struct { */ typedef int (*git_diff_file_fn)( void *cb_data, - git_diff_delta *delta, + const git_diff_delta *delta, float progress); /** @@ -145,8 +204,8 @@ typedef struct { */ typedef int (*git_diff_hunk_fn)( void *cb_data, - git_diff_delta *delta, - git_diff_range *range, + const git_diff_delta *delta, + const git_diff_range *range, const char *header, size_t header_len); @@ -155,20 +214,21 @@ typedef int (*git_diff_hunk_fn)( * * These values describe where a line came from and will be passed to * the git_diff_data_fn when iterating over a diff. There are some - * special origin contants at the end that are used for the text + * special origin constants at the end that are used for the text * output callbacks to demarcate lines that are actually part of * the file or hunk headers. */ enum { - /* these values will be sent to `git_diff_data_fn` along with the line */ + /* These values will be sent to `git_diff_data_fn` along with the line */ GIT_DIFF_LINE_CONTEXT = ' ', GIT_DIFF_LINE_ADDITION = '+', GIT_DIFF_LINE_DELETION = '-', - GIT_DIFF_LINE_ADD_EOFNL = '\n', /**< LF was added at end of file */ + GIT_DIFF_LINE_ADD_EOFNL = '\n', /**< Removed line w/o LF & added one with */ GIT_DIFF_LINE_DEL_EOFNL = '\0', /**< LF was removed at end of file */ - /* these values will only be sent to a `git_diff_data_fn` when the content - * of a diff is being formatted (eg. through git_diff_print_patch() or - * git_diff_print_compact(), for instance). + + /* The following values will only be sent to a `git_diff_data_fn` when + * the content of a diff is being formatted (eg. through + * git_diff_print_patch() or git_diff_print_compact(), for instance). */ GIT_DIFF_LINE_FILE_HDR = 'F', GIT_DIFF_LINE_HUNK_HDR = 'H', @@ -185,12 +245,21 @@ enum { */ typedef int (*git_diff_data_fn)( void *cb_data, - git_diff_delta *delta, - git_diff_range *range, + const git_diff_delta *delta, + const git_diff_range *range, char line_origin, /**< GIT_DIFF_LINE_... value from above */ const char *content, size_t content_len); +/** + * The diff patch is used to store all the text diffs for a delta. + * + * You can easily loop over the content of patches and get information about + * them. + */ +typedef struct git_diff_patch git_diff_patch; + + /** @name Diff List Generator Functions * * These are the functions you would use to create (or destroy) a @@ -206,6 +275,8 @@ GIT_EXTERN(void) git_diff_list_free(git_diff_list *diff); /** * Compute a difference between two tree objects. * + * This is equivalent to `git diff ` + * * @param repo The repository containing the trees. * @param opts Structure with options to influence diff or NULL for defaults. * @param old_tree A git_tree object to diff from. @@ -222,6 +293,9 @@ GIT_EXTERN(int) git_diff_tree_to_tree( /** * Compute a difference between a tree and the index. * + * This is equivalent to `git diff --cached ` or if you pass + * the HEAD tree, then like `git diff --cached`. + * * @param repo The repository containing the tree and index. * @param opts Structure with options to influence diff or NULL for defaults. * @param old_tree A git_tree object to diff from. @@ -236,6 +310,11 @@ GIT_EXTERN(int) git_diff_index_to_tree( /** * Compute a difference between the working directory and the index. * + * This matches the `git diff` command. See the note below on + * `git_diff_workdir_to_tree` for a discussion of the difference between + * `git diff` and `git diff HEAD` and how to emulate a `git diff ` + * using libgit2. + * * @param repo The repository. * @param opts Structure with options to influence diff or NULL for defaults. * @param diff A pointer to a git_diff_list pointer that will be allocated. @@ -248,14 +327,24 @@ GIT_EXTERN(int) git_diff_workdir_to_index( /** * Compute a difference between the working directory and a tree. * - * This returns strictly the differences between the tree and the - * files contained in the working directory, regardless of the state - * of files in the index. There is no direct equivalent in C git. + * This is *NOT* the same as `git diff `. Running `git diff HEAD` + * or the like actually uses information from the index, along with the tree + * and workdir dir info. * - * This is *NOT* the same as 'git diff HEAD' or 'git diff '. Those - * commands diff the tree, the index, and the workdir. To emulate those - * functions, call `git_diff_index_to_tree` and `git_diff_workdir_to_index`, - * then call `git_diff_merge` on the results. + * 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 `, you should call both + * `git_diff_index_to_tree` and `git_diff_workdir_to_index`, then call + * `git_diff_merge` on the results. That will yield a `git_diff_list` 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. * * @param repo The repository containing the tree. * @param opts Structure with options to influence diff or NULL for defaults. @@ -296,12 +385,29 @@ GIT_EXTERN(int) git_diff_merge( /**@{*/ /** - * Iterate over a diff list issuing callbacks. + * Loop over all deltas in a diff list issuing callbacks. * - * If the hunk and/or line callbacks are not NULL, then this will calculate - * text diffs for all files it thinks are not binary. If those are both - * NULL, then this will not bother with the text diffs, so it can be - * efficient. + * This will iterate through all of the files described in a diff. You + * should provide a file callback to learn about each file. + * + * The "hunk" and "line" callbacks are optional, and the text diff of the + * files will only be calculated if they are not NULL. Of course, these + * callbacks will not be invoked for binary files on the diff list or for + * files whose only changed is a file mode change. + * + * Returning a non-zero value from any of the callbacks will terminate + * the iteration and cause this return `GIT_EUSER`. + * + * @param diff A git_diff_list generated by one of the above functions. + * @param cb_data Reference pointer that will be passed to your callbacks. + * @param file_cb Callback function to make per file in the diff. + * @param hunk_cb Optional callback to make per hunk of text diff. This + * callback is called to describe a range of lines in the + * diff. It will not be issued for binary files. + * @param line_cb Optional callback to make per line of diff text. This + * same callback will be made for context lines, added, and + * removed lines, and even for a deleted trailing newline. + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_diff_foreach( git_diff_list *diff, @@ -312,22 +418,191 @@ GIT_EXTERN(int) git_diff_foreach( /** * Iterate over a diff generating text output like "git diff --name-status". + * + * Returning a non-zero value from the callbacks will terminate the + * iteration and cause this return `GIT_EUSER`. + * + * @param diff A git_diff_list generated by one of the above functions. + * @param cb_data Reference pointer that will be passed to your callback. + * @param print_cb Callback to make per line of diff text. + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_diff_print_compact( git_diff_list *diff, void *cb_data, git_diff_data_fn print_cb); +/** + * Look up the single character abbreviation for a delta status code. + * + * When you call `git_diff_print_compact` it prints single letter codes into + * the output such as 'A' for added, 'D' for deleted, 'M' for modified, etc. + * It is sometimes convenient to convert a git_delta_t value into these + * letters for your own purposes. This function does just that. By the + * way, unmodified will return a space (i.e. ' '). + * + * @param delta_t The git_delta_t value to look up + * @return The single character label for that code + */ +GIT_EXTERN(char) git_diff_status_char(git_delta_t status); + /** * Iterate over a diff generating text output like "git diff". * * This is a super easy way to generate a patch from a diff. + * + * Returning a non-zero value from the callbacks will terminate the + * iteration and cause this return `GIT_EUSER`. + * + * @param diff A git_diff_list generated by one of the above functions. + * @param cb_data Reference pointer that will be passed to your callbacks. + * @param print_cb Callback function to output lines of the diff. This + * same function will be called for file headers, hunk + * headers, and diff lines. Fortunately, you can probably + * use various GIT_DIFF_LINE constants to determine what + * text you are given. + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_diff_print_patch( git_diff_list *diff, void *cb_data, git_diff_data_fn print_cb); +/** + * Query how many diff records are there in a diff list. + * + * @param diff A git_diff_list generated by one of the above functions + * @return Count of number of deltas in the list + */ +GIT_EXTERN(size_t) git_diff_num_deltas(git_diff_list *diff); + +/** + * Query how many diff deltas are there in a diff list filtered by type. + * + * This works just like `git_diff_entrycount()` with an extra parameter + * that is a `git_delta_t` and returns just the count of how many deltas + * match that particular type. + * + * @param diff A git_diff_list generated by one of the above functions + * @param type A git_delta_t value to filter the count + * @return Count of number of deltas matching delta_t type + */ +GIT_EXTERN(size_t) git_diff_num_deltas_of_type( + git_diff_list *diff, + git_delta_t type); + +/** + * Return the diff delta and patch for an entry in the diff list. + * + * The `git_diff_patch` is a newly created object contains the text diffs + * for the delta. You have to call `git_diff_patch_free()` when you are + * done with it. You can use the patch object to loop over all the hunks + * and lines in the diff of the one delta. + * + * For an unchanged file or a binary file, no `git_diff_patch` will be + * created, the output will be set to NULL, and the `binary` flag will be + * set true in the `git_diff_delta` structure. + * + * The `git_diff_delta` pointer points to internal data and you do not have + * to release it when you are done with it. It will go away when the + * `git_diff_list` and `git_diff_patch` go away. + * + * It is okay to pass NULL for either of the output parameters; if you pass + * NULL for the `git_diff_patch`, then the text diff will not be calculated. + * + * @param patch Output parameter for the delta patch object + * @param delta Output parameter for the delta object + * @param diff Diff list object + * @param idx Index into diff list + * @return 0 on success, other value < 0 on error + */ +GIT_EXTERN(int) git_diff_get_patch( + git_diff_patch **patch, + const git_diff_delta **delta, + git_diff_list *diff, + size_t idx); + +/** + * Free a git_diff_patch object. + */ +GIT_EXTERN(void) git_diff_patch_free( + git_diff_patch *patch); + +/** + * Get the delta associated with a patch + */ +GIT_EXTERN(const git_diff_delta *) git_diff_patch_delta( + git_diff_patch *patch); + +/** + * Get the number of hunks in a patch + */ +GIT_EXTERN(size_t) git_diff_patch_num_hunks( + git_diff_patch *patch); + +/** + * Get the information about a hunk in a patch + * + * Given a patch and a hunk index into the patch, this returns detailed + * information about that hunk. Any of the output pointers can be passed + * as NULL if you don't care about that particular piece of information. + * + * @param range Output pointer to git_diff_range of hunk + * @param header Output pointer to header string for hunk. Unlike the + * content pointer for each line, this will be NUL-terminated + * @param header_len Output value of characters in header string + * @param lines_in_hunk Output count of total lines in this hunk + * @param patch Input pointer to patch object + * @param hunk_idx Input index of hunk to get information about + * @return 0 on success, GIT_ENOTFOUND if hunk_idx out of range, <0 on error + */ +GIT_EXTERN(int) git_diff_patch_get_hunk( + const git_diff_range **range, + const char **header, + size_t *header_len, + size_t *lines_in_hunk, + git_diff_patch *patch, + size_t hunk_idx); + +/** + * Get the number of lines in a hunk. + * + * @param patch The git_diff_patch object + * @param hunk_idx Index of the hunk + * @return Number of lines in hunk or -1 if invalid hunk index + */ +GIT_EXTERN(int) git_diff_patch_num_lines_in_hunk( + git_diff_patch *patch, + size_t hunk_idx); + +/** + * Get data about a line in a hunk of a patch. + * + * Given a patch, a hunk index, and a line index in the hunk, this + * will return a lot of details about that line. If you pass a hunk + * index larger than the number of hunks or a line index larger than + * the number of lines in the hunk, this will return -1. + * + * @param line_origin A GIT_DIFF_LINE constant from above + * @param content Pointer to content of diff line, not NUL-terminated + * @param content_len Number of characters in content + * @param old_lineno Line number in old file or -1 if line is added + * @param new_lineno Line number in new file or -1 if line is deleted + * @param patch The patch to look in + * @param hunk_idx The index of the hunk + * @param line_of_index The index of the line in the hunk + * @return 0 on success, <0 on failure + */ +GIT_EXTERN(int) git_diff_patch_get_line_in_hunk( + char *line_origin, + const char **content, + size_t *content_len, + int *old_lineno, + int *new_lineno, + git_diff_patch *patch, + size_t hunk_idx, + size_t line_of_hunk); + /**@}*/ @@ -338,18 +613,21 @@ GIT_EXTERN(int) git_diff_print_patch( /** * Directly run a text diff on two blobs. * - * Compared to a file, a blob lacks some contextual information. As such, the - * `git_diff_file` parameters of the callbacks will be filled accordingly to the following: - * `mode` will be set to 0, `path` will be set to NULL. When dealing with a NULL blob, `oid` - * will be set to 0. + * Compared to a file, a blob lacks some contextual information. As such, + * the `git_diff_file` parameters of the callbacks will be filled + * accordingly to the following: `mode` will be set to 0, `path` will be set + * to NULL. When dealing with a NULL blob, `oid` will be set to 0. * - * When at least one of the blobs being dealt with is binary, the `git_diff_delta` binary - * attribute will be set to 1 and no call to the hunk_cb nor line_cb will be made. + * When at least one of the blobs being dealt with is binary, the + * `git_diff_delta` binary attribute will be set to 1 and no call to the + * hunk_cb nor line_cb will be made. + * + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_diff_blobs( git_blob *old_blob, git_blob *new_blob, - git_diff_options *options, + const git_diff_options *options, void *cb_data, git_diff_file_fn file_cb, git_diff_hunk_fn hunk_cb, diff --git a/git2/include/git2/errors.h b/git2/include/git2/errors.h index fb6670004..fb56dcc6b 100644 --- a/git2/include/git2/errors.h +++ b/git2/include/git2/errors.h @@ -17,43 +17,6 @@ */ GIT_BEGIN_DECL -#ifdef GIT_OLD_ERRORS -enum { - GIT_SUCCESS = 0, - GIT_ENOTOID = -2, - GIT_ENOTFOUND = -3, - GIT_ENOMEM = -4, - GIT_EOSERR = -5, - GIT_EOBJTYPE = -6, - GIT_ENOTAREPO = -7, - GIT_EINVALIDTYPE = -8, - GIT_EMISSINGOBJDATA = -9, - GIT_EPACKCORRUPTED = -10, - GIT_EFLOCKFAIL = -11, - GIT_EZLIB = -12, - GIT_EBUSY = -13, - GIT_EBAREINDEX = -14, - GIT_EINVALIDREFNAME = -15, - GIT_EREFCORRUPTED = -16, - GIT_ETOONESTEDSYMREF = -17, - GIT_EPACKEDREFSCORRUPTED = -18, - GIT_EINVALIDPATH = -19, - GIT_EREVWALKOVER = -20, - GIT_EINVALIDREFSTATE = -21, - GIT_ENOTIMPLEMENTED = -22, - GIT_EEXISTS = -23, - GIT_EOVERFLOW = -24, - GIT_ENOTNUM = -25, - GIT_ESTREAM = -26, - GIT_EINVALIDARGS = -27, - GIT_EOBJCORRUPTED = -28, - GIT_EAMBIGUOUS = -29, - GIT_EPASSTHROUGH = -30, - GIT_ENOMATCH = -31, - GIT_ESHORTBUFFER = -32, -}; -#endif - /** Generic return codes */ enum { GIT_OK = 0, @@ -62,9 +25,13 @@ enum { GIT_EEXISTS = -4, GIT_EAMBIGUOUS = -5, GIT_EBUFS = -6, + GIT_EUSER = -7, + GIT_EBAREREPO = -8, + GIT_EORPHANEDHEAD = -9, + GIT_EUNMERGED = -10, GIT_PASSTHROUGH = -30, - GIT_REVWALKOVER = -31, + GIT_ITEROVER = -31, }; typedef struct { @@ -72,6 +39,7 @@ typedef struct { int klass; } git_error; +/** Error classes */ typedef enum { GITERR_NOMEMORY, GITERR_OS, @@ -88,6 +56,9 @@ typedef enum { GITERR_TAG, GITERR_TREE, GITERR_INDEXER, + GITERR_SSL, + GITERR_SUBMODULE, + GITERR_THREAD, } git_error_t; /** @@ -103,6 +74,40 @@ GIT_EXTERN(const git_error *) giterr_last(void); */ GIT_EXTERN(void) giterr_clear(void); +/** + * Set the error message string for this thread. + * + * This function is public so that custom ODB backends and the like can + * relay an error message through libgit2. Most regular users of libgit2 + * will never need to call this function -- actually, calling it in most + * circumstances (for example, calling from within a callback function) + * will just end up having the value overwritten by libgit2 internals. + * + * This error message is stored in thread-local storage and only applies + * to the particular thread that this libgit2 call is made from. + * + * NOTE: Passing the `error_class` as GITERR_OS has a special behavior: we + * attempt to append the system default error message for the last OS error + * that occurred and then clear the last error. The specific implementation + * of looking up and clearing this last OS error will vary by platform. + * + * @param error_class One of the `git_error_t` enum above describing the + * general subsystem that is responsible for the error. + * @param message The formatted error message to keep + */ +GIT_EXTERN(void) giterr_set_str(int error_class, const char *string); + +/** + * Set the error message to a special value for memory allocation failure. + * + * The normal `giterr_set_str()` function attempts to `strdup()` the string + * that is passed in. This is not a good idea when the error in question + * is a memory allocation failure. That circumstance has a special setter + * function that sets the error string to a known and statically allocated + * internal value. + */ +GIT_EXTERN(void) giterr_set_oom(void); + /** @} */ GIT_END_DECL #endif diff --git a/git2/include/git2/ignore.h b/git2/include/git2/ignore.h new file mode 100644 index 000000000..e18615edd --- /dev/null +++ b/git2/include/git2/ignore.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2012 the libgit2 contributors + * + * 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_ignore_h__ +#define INCLUDE_git_ignore_h__ + +#include "common.h" +#include "types.h" + +GIT_BEGIN_DECL + +/** + * Add ignore rules for a repository. + * + * Excludesfile rules (i.e. .gitignore rules) are generally read from + * .gitignore files in the repository tree or from a shared system file + * only if a "core.excludesfile" config value is set. The library also + * keeps a set of per-repository internal ignores that can be configured + * in-memory and will not persist. This function allows you to add to + * that internal rules list. + * + * Example usage: + * + * error = git_ignore_add_rule(myrepo, "*.c\ndir/\nFile with space\n"); + * + * This would add three rules to the ignores. + * + * @param repo The repository to add ignore rules to. + * @param rules Text of rules, a la the contents of a .gitignore file. + * It is okay to have multiple rules in the text; if so, + * each rule should be terminated with a newline. + * @return 0 on success + */ +GIT_EXTERN(int) git_ignore_add_rule( + git_repository *repo, + const char *rules); + +/** + * Clear ignore rules that were explicitly added. + * + * Clears the internal ignore rules that have been set up. This will not + * turn off the rules in .gitignore files that actually exist in the + * filesystem. + * + * @param repo The repository to remove ignore rules from. + * @return 0 on success + */ +GIT_EXTERN(int) git_ignore_clear_internal_rules( + git_repository *repo); + +/** + * Test if the ignore rules apply to a given path. + * + * This function checks the ignore rules to see if they would apply to the + * given file. This indicates if the file would be ignored regardless of + * whether the file is already in the index or commited to the repository. + * + * One way to think of this is if you were to do "git add ." on the + * directory containing the file, would it be added or not? + * + * @param ignored boolean returning 0 if the file is not ignored, 1 if it is + * @param repo a repository object + * @param path the file to check ignores for, relative to the repo's workdir. + * @return 0 if ignore rules could be processed for the file (regardless + * of whether it exists or not), or an error < 0 if they could not. + */ +GIT_EXTERN(int) git_ignore_path_is_ignored( + int *ignored, + git_repository *repo, + const char *path); + +GIT_END_DECL + +#endif diff --git a/git2/include/git2/index.h b/git2/include/git2/index.h index 6a42c8515..d8282e80f 100644 --- a/git2/include/git2/index.h +++ b/git2/include/git2/index.h @@ -8,6 +8,7 @@ #define INCLUDE_git_index_h__ #include "common.h" +#include "indexer.h" #include "types.h" #include "oid.h" @@ -90,6 +91,14 @@ typedef struct git_index_entry_unmerged { char *path; } git_index_entry_unmerged; +/** Capabilities of system that affect index actions. */ +enum { + GIT_INDEXCAP_IGNORE_CASE = 1, + GIT_INDEXCAP_NO_FILEMODE = 2, + GIT_INDEXCAP_NO_SYMLINKS = 4, + GIT_INDEXCAP_FROM_OWNER = ~0u +}; + /** * Create a new bare Git index object as a memory representation * of the Git index file in 'index_path', without a repository @@ -126,6 +135,27 @@ GIT_EXTERN(void) git_index_clear(git_index *index); */ GIT_EXTERN(void) git_index_free(git_index *index); +/** + * Read index capabilities flags. + * + * @param index An existing index object + * @return A combination of GIT_INDEXCAP values + */ +GIT_EXTERN(unsigned int) git_index_caps(const git_index *index); + +/** + * Set index capabilities flags. + * + * If you pass `GIT_INDEXCAP_FROM_OWNER` for the caps, then the + * capabilities will be read from the config of the owner object, + * looking at `core.ignorecase`, `core.filemode`, `core.symlinks`. + * + * @param index An existing index object + * @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); + /** * Update the contents of an existing index object in memory * by reading from the hard disk. @@ -250,7 +280,7 @@ GIT_EXTERN(int) git_index_remove(git_index *index, int position); * @param n the position of the entry * @return a pointer to the entry; NULL if out of bounds */ -GIT_EXTERN(git_index_entry *) git_index_get(git_index *index, unsigned int n); +GIT_EXTERN(git_index_entry *) git_index_get(git_index *index, size_t n); /** * Get the count of entries currently in the index @@ -290,12 +320,12 @@ GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_bypath(git_i * @param n the position of the entry * @return a pointer to the unmerged entry; NULL if out of bounds */ -GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_byindex(git_index *index, unsigned int n); +GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_byindex(git_index *index, size_t n); /** * Return the stage number from a git index entry * - * This entry is calculated from the entrie's flag + * This entry is calculated from the entry's flag * attribute like this: * * (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT @@ -306,9 +336,10 @@ GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_byindex(git_ GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry); /** - * Read a tree into the index file + * Read a tree into the index file with stats * - * The current index contents will be replaced by the specified tree. + * The current index contents will be replaced by the specified tree. The total + * node count is collected in stats. * * @param index an existing index object * @param tree tree to read diff --git a/git2/include/git2/indexer.h b/git2/include/git2/indexer.h index 14bd0e402..a2a155473 100644 --- a/git2/include/git2/indexer.h +++ b/git2/include/git2/indexer.h @@ -16,22 +16,35 @@ GIT_BEGIN_DECL * This is passed as the first argument to the callback to allow the * user to see the progress. */ -typedef struct git_indexer_stats { - unsigned int total; - unsigned int processed; -} git_indexer_stats; +typedef struct git_transfer_progress { + unsigned int total_objects; + unsigned int indexed_objects; + unsigned int received_objects; + size_t received_bytes; +} git_transfer_progress; +/** + * Type for progress callbacks during indexing + */ +typedef void (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload); + typedef struct git_indexer git_indexer; typedef struct git_indexer_stream git_indexer_stream; /** * Create a new streaming indexer instance * - * @param out where to store the inexer instance - * @param path to the gitdir (metadata directory) + * @param out where to store the indexer instance + * @param path to the directory where the packfile should be stored + * @param progress_cb function to call with progress information + * @param progress_payload payload for the progress callback */ -GIT_EXTERN(int) git_indexer_stream_new(git_indexer_stream **out, const char *gitdir); +GIT_EXTERN(int) git_indexer_stream_new( + git_indexer_stream **out, + const char *path, + git_transfer_progress_callback progress_cb, + void *progress_callback_payload); /** * Add data to the indexer @@ -41,7 +54,7 @@ GIT_EXTERN(int) git_indexer_stream_new(git_indexer_stream **out, const char *git * @param size the size of the data * @param stats stat storage */ -GIT_EXTERN(int) git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_indexer_stats *stats); +GIT_EXTERN(int) git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats); /** * Finalize the pack and index @@ -50,7 +63,7 @@ GIT_EXTERN(int) git_indexer_stream_add(git_indexer_stream *idx, const void *data * * @param idx the indexer */ -GIT_EXTERN(int) git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stats); +GIT_EXTERN(int) git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *stats); /** * Get the packfile's hash @@ -87,7 +100,7 @@ GIT_EXTERN(int) git_indexer_new(git_indexer **out, const char *packname); * @param idx the indexer instance * @param stats storage for the running state */ -GIT_EXTERN(int) git_indexer_run(git_indexer *idx, git_indexer_stats *stats); +GIT_EXTERN(int) git_indexer_run(git_indexer *idx, git_transfer_progress *stats); /** * Write the index file to disk. diff --git a/git2/include/git2/merge.h b/git2/include/git2/merge.h index 5a0b2e7f2..37b1c787d 100644 --- a/git2/include/git2/merge.h +++ b/git2/include/git2/merge.h @@ -28,7 +28,17 @@ GIT_BEGIN_DECL * @param one one of the commits * @param two the other commit */ -GIT_EXTERN(int) git_merge_base(git_oid *out, git_repository *repo, git_oid *one, git_oid *two); +GIT_EXTERN(int) git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const git_oid *two); + +/** + * Find a merge base given a list of commits + * + * @param out the OID of a merge base considering all the commits + * @param repo the repository where the commits exist + * @param input_array oids of the commits + * @param length The number of commits in the provided `input_array` + */ +GIT_EXTERN(int) git_merge_base_many(git_oid *out, git_repository *repo, const git_oid input_array[], size_t length); /** @} */ GIT_END_DECL diff --git a/git2/include/git2/message.h b/git2/include/git2/message.h new file mode 100644 index 000000000..b42cb7677 --- /dev/null +++ b/git2/include/git2/message.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * 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_message_h__ +#define INCLUDE_git_message_h__ + +#include "common.h" + +/** + * @file git2/message.h + * @brief Git message management routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Clean up message from excess whitespace and make sure that the last line + * ends with a '\n'. + * + * Optionally, can remove lines starting with a "#". + * + * @param message_out The user allocated buffer which will be filled with + * the cleaned up message. Pass NULL if you just want to get the size of the + * prettified message as the output value. + * + * @param size The size of the allocated buffer message_out. + * + * @param message The message to be prettified. + * + * @param strip_comments 1 to remove lines starting with a "#", 0 otherwise. + * + * @return -1 on error, else number of characters in prettified message + * including the trailing NUL byte + */ +GIT_EXTERN(int) git_message_prettify(char *message_out, size_t buffer_size, const char *message, int strip_comments); + +/** @} */ +GIT_END_DECL +#endif /* INCLUDE_git_message_h__ */ diff --git a/git2/include/git2/notes.h b/git2/include/git2/notes.h index 19073abd1..af480a408 100644 --- a/git2/include/git2/notes.h +++ b/git2/include/git2/notes.h @@ -23,10 +23,11 @@ GIT_BEGIN_DECL * * The note must be freed manually by the user. * - * @param note the note; NULL in case of error - * @param repo the Git repository - * @param notes_ref OID reference to use (optional); defaults to "refs/notes/commits" - * @param oid OID of the object + * @param note pointer to the read note; NULL in case of error + * @param repo repository where to look up the note + * @param notes_ref canonical name of the reference to use (optional); + * defaults to "refs/notes/commits" + * @param oid OID of the git object to read the note from * * @return 0 or an error code */ @@ -50,17 +51,17 @@ GIT_EXTERN(const char *) git_note_message(git_note *note); */ GIT_EXTERN(const git_oid *) git_note_oid(git_note *note); - /** * Add a note for an object * - * @param oid pointer to store the OID (optional); NULL in case of error - * @param repo the Git repository + * @param out pointer to store the OID (optional); NULL in case of error + * @param repo repository where to store the note * @param author signature of the notes commit author * @param committer signature of the notes commit committer - * @param notes_ref OID reference to update (optional); defaults to "refs/notes/commits" - * @param oid The OID of the object - * @param oid The note to add for object oid + * @param notes_ref canonical name of the reference to use (optional); + * defaults to "refs/notes/commits" + * @param oid OID of the git object to decorate + * @param note Content of the note to add for object oid * * @return 0 or an error code */ @@ -73,11 +74,12 @@ GIT_EXTERN(int) git_note_create(git_oid *out, git_repository *repo, /** * Remove the note for an object * - * @param repo the Git repository - * @param notes_ref OID reference to use (optional); defaults to "refs/notes/commits" + * @param repo repository where the note lives + * @param notes_ref canonical name of the reference to use (optional); + * defaults to "refs/notes/commits" * @param author signature of the notes commit author * @param committer signature of the notes commit committer - * @param oid the oid which note's to be removed + * @param oid OID of the git object to remove the note from * * @return 0 or an error code */ @@ -119,19 +121,21 @@ typedef struct { * * @param repo Repository where to find the notes. * - * @param notes_ref OID reference to read from (optional); defaults to "refs/notes/commits". + * @param notes_ref Reference to read from (optional); defaults to + * "refs/notes/commits". * - * @param note_cb Callback to invoke per found annotation. + * @param note_cb Callback to invoke per found annotation. Return non-zero + * to stop looping. * * @param payload Extra parameter to callback function. * - * @return 0 or an error code. + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_note_foreach( - git_repository *repo, - const char *notes_ref, - int (*note_cb)(git_note_data *note_data, void *payload), - void *payload + git_repository *repo, + const char *notes_ref, + int (*note_cb)(git_note_data *note_data, void *payload), + void *payload ); /** @} */ diff --git a/git2/include/git2/object.h b/git2/include/git2/object.h index 9e988b7b6..fd6ae95c1 100644 --- a/git2/include/git2/object.h +++ b/git2/include/git2/object.h @@ -21,7 +21,7 @@ GIT_BEGIN_DECL /** - * Lookup a reference to one of the objects in a repostory. + * Lookup a reference to one of the objects in a repository. * * The generated reference is owned by the repository and * should be closed with the `git_object_free` method @@ -45,7 +45,7 @@ GIT_EXTERN(int) git_object_lookup( git_otype type); /** - * Lookup a reference to one of the objects in a repostory, + * Lookup a reference to one of the objects in a repository, * given a prefix of its identifier (short id). * * The object obtained will be so that its identifier @@ -75,7 +75,7 @@ GIT_EXTERN(int) git_object_lookup_prefix( git_object **object_out, git_repository *repo, const git_oid *id, - unsigned int len, + size_t len, git_otype type); /** @@ -114,7 +114,7 @@ GIT_EXTERN(git_repository *) git_object_owner(const git_object *obj); * This method instructs the library to close an existing * object; note that git_objects are owned and cached by the repository * so the object may or may not be freed after this library call, - * depending on how agressive is the caching mechanism used + * depending on how aggressive is the caching mechanism used * by the repository. * * IMPORTANT: @@ -167,6 +167,26 @@ GIT_EXTERN(int) git_object_typeisloose(git_otype type); */ GIT_EXTERN(size_t) git_object__size(git_otype type); +/** + * Recursively peel an object until an object of the specified type is met. + * + * The retrieved `peeled` object is owned by the repository and should be + * closed with the `git_object_free` method. + * + * If you pass `GIT_OBJ_ANY` as the target type, then the object will be + * peeled until the type changes (e.g. a tag will be chased until the + * referenced object is no longer a tag). + * + * @param peeled Pointer to the peeled git_object + * @param object The object to be processed + * @param target_type The type of the requested object + * @return 0 or an error code + */ +GIT_EXTERN(int) git_object_peel( + git_object **peeled, + git_object *object, + git_otype target_type); + /** @} */ GIT_END_DECL diff --git a/git2/include/git2/odb.h b/git2/include/git2/odb.h index 1df193389..c6e73571b 100644 --- a/git2/include/git2/odb.h +++ b/git2/include/git2/odb.h @@ -62,7 +62,7 @@ GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir); * @param odb database to add the backend to * @param backend pointer to a git_odb_backend instance * @param priority Value for ordering the backends queue - * @return 0 on sucess; error code otherwise + * @return 0 on success; error code otherwise */ GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority); @@ -83,7 +83,7 @@ GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int * @param odb database to add the backend to * @param backend pointer to a git_odb_backend instance * @param priority Value for ordering the backends queue - * @return 0 on sucess; error code otherwise + * @return 0 on success; error code otherwise */ GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority); @@ -139,7 +139,7 @@ GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *i * GIT_ENOTFOUND if the object is not in the database. * GIT_EAMBIGUOUS if the prefix is ambiguous (several objects match the prefix) */ -GIT_EXTERN(int) git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_id, unsigned int len); +GIT_EXTERN(int) git_odb_read_prefix(git_odb_object **out, git_odb *db, const git_oid *short_id, size_t len); /** * Read the header of an object from the database, without @@ -172,6 +172,21 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *d */ GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id); +/** + * List all objects available in the database + * + * The callback will be called for each object available in the + * database. Note that the objects are likely to be returned in the index + * order, which would make accessing the objects in that order inefficient. + * Return a non-zero value from the callback to stop looping. + * + * @param db database to use + * @param cb the callback to call for each object + * @param data data to pass to the callback + * @return 0 on success, GIT_EUSER on non-zero callback, or error code + */ +GIT_EXTERN(int) git_odb_foreach(git_odb *db, int (*cb)(git_oid *oid, void *data), void *data); + /** * Write an object directly into the ODB * @@ -185,7 +200,7 @@ GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id); * * @param oid pointer to store the OID result of the write * @param odb object database where to store the object - * @param data buffer with the data to storr + * @param data buffer with the data to store * @param len size of the buffer * @param type type of the data to store * @return 0 or an error code @@ -250,7 +265,7 @@ GIT_EXTERN(int) git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const /** * Determine the object-ID (sha1 hash) of a data buffer * - * The resulting SHA-1 OID will the itentifier for the data + * The resulting SHA-1 OID will be the identifier for the data * buffer as if the data buffer it were to written to the ODB. * * @param id the resulting object-ID. @@ -264,8 +279,10 @@ GIT_EXTERN(int) git_odb_hash(git_oid *id, const void *data, size_t len, git_otyp /** * Read a file from disk and fill a git_oid with the object id * that the file would have if it were written to the Object - * Database as an object of the given type. Similar functionality - * to git.git's `git hash-object` without the `-w` flag. + * Database as an object of the given type (w/o applying filters). + * Similar functionality to git.git's `git hash-object` without + * the `-w` flag, however, with the --no-filters flag. + * If you need filters, see git_repository_hashfile. * * @param out oid structure the result is written into. * @param path file to read and determine object id for diff --git a/git2/include/git2/odb_backend.h b/git2/include/git2/odb_backend.h index f4620f5f4..cb8069787 100644 --- a/git2/include/git2/odb_backend.h +++ b/git2/include/git2/odb_backend.h @@ -26,6 +26,10 @@ struct git_odb_stream; struct git_odb_backend { git_odb *odb; + /* read and read_prefix each return to libgit2 a buffer which + * will be freed later. The buffer should be allocated using + * the function git_odb_backend_malloc to ensure that it can + * be safely freed later. */ int (* read)( void **, size_t *, git_otype *, struct git_odb_backend *, @@ -42,7 +46,7 @@ struct git_odb_backend { void **, size_t *, git_otype *, struct git_odb_backend *, const git_oid *, - unsigned int); + size_t); int (* read_header)( size_t *, git_otype *, @@ -71,6 +75,12 @@ struct git_odb_backend { struct git_odb_backend *, const git_oid *); + int (*foreach)( + struct git_odb_backend *, + int (*cb)(git_oid *oid, void *data), + void *data + ); + void (* free)(struct git_odb_backend *); }; @@ -94,6 +104,9 @@ struct git_odb_stream { GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir); GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir, int compression_level, int do_fsync); +GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **backend_out, const char *index_file); + +GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len); GIT_END_DECL diff --git a/git2/include/git2/oid.h b/git2/include/git2/oid.h index c06458d24..9e54a9f96 100644 --- a/git2/include/git2/oid.h +++ b/git2/include/git2/oid.h @@ -84,7 +84,7 @@ GIT_EXTERN(void) git_oid_fmt(char *str, const git_oid *oid); * Format a git_oid into a loose-object path string. * * The resulting string is "aa/...", where "aa" is the first two - * hex digitis of the oid and "..." is the remaining 38 digits. + * hex digits of the oid and "..." is the remaining 38 digits. * * @param str output hex string; must be pointing at the start of * the hex sequence and have at least the number of bytes @@ -136,7 +136,31 @@ GIT_EXTERN(void) git_oid_cpy(git_oid *out, const git_oid *src); * @param b second oid structure. * @return <0, 0, >0 if a < b, a == b, a > b. */ -GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b); +GIT_INLINE(int) git_oid_cmp(const git_oid *a, const git_oid *b) +{ + const unsigned char *sha1 = a->id; + const unsigned char *sha2 = b->id; + int i; + + for (i = 0; i < GIT_OID_RAWSZ; i++, sha1++, sha2++) { + if (*sha1 != *sha2) + return *sha1 - *sha2; + } + + return 0; +} + +/** + * Compare two oid structures for equality + * + * @param a first oid structure. + * @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); +} /** * Compare the first 'len' hexadecimal characters (packets of 4 bits) @@ -147,7 +171,7 @@ GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b); * @param len the number of hex chars to compare * @return 0 in case of a match */ -GIT_EXTERN(int) git_oid_ncmp(const git_oid *a, const git_oid *b, unsigned int len); +GIT_EXTERN(int) git_oid_ncmp(const git_oid *a, const git_oid *b, size_t len); /** * Check if an oid equals an hex formatted object id. @@ -161,6 +185,8 @@ GIT_EXTERN(int) git_oid_streq(const git_oid *a, const char *str); /** * Check is an oid is all zeros. + * + * @return 1 if all zeros, 0 otherwise. */ GIT_EXTERN(int) git_oid_iszero(const git_oid *a); diff --git a/git2/include/git2/pack.h b/git2/include/git2/pack.h new file mode 100644 index 000000000..748ad2e11 --- /dev/null +++ b/git2/include/git2/pack.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * 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_pack_h__ +#define INCLUDE_git_pack_h__ + +#include "common.h" +#include "oid.h" + +/** + * @file git2/pack.h + * @brief Git pack management routines + * @defgroup git_pack Git pack management routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Initialize a new packbuilder + * + * @param out The new packbuilder object + * @param repo The repository + * + * @return 0 or an error code + */ +GIT_EXTERN(int) git_packbuilder_new(git_packbuilder **out, git_repository *repo); + +/** + * Set number of threads to spawn + * + * By default, libgit2 won't spawn any threads at all; + * when set to 0, libgit2 will autodetect the number of + * CPUs. + * + * @param pb The packbuilder + * @param n Number of threads to spawn + */ +GIT_EXTERN(void) git_packbuilder_set_threads(git_packbuilder *pb, unsigned int n); + +/** + * Insert a single object + * + * For an optimal pack it's mandatory to insert objects in recency order, + * commits followed by trees and blobs. + * + * @param pb The packbuilder + * @param oid The oid of the commit + * @param oid The name; might be NULL + * + * @return 0 or an error code + */ +GIT_EXTERN(int) git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, const char *name); + +/** + * Insert a root tree object + * + * This will add the tree as well as all referenced trees and blobs. + * + * @param pb The packbuilder + * @param oid The oid of the root tree + * + * @return 0 or an error code + */ +GIT_EXTERN(int) git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *oid); + +/** + * Write the new pack and the corresponding index to path + * + * @param pb The packbuilder + * @param path Directory to store the new pack and index + * + * @return 0 or an error code + */ +GIT_EXTERN(int) git_packbuilder_write(git_packbuilder *pb, const char *file); + +/** + * Free the packbuilder and all associated data + * + * @param pb The packbuilder + */ +GIT_EXTERN(void) git_packbuilder_free(git_packbuilder *pb); + +/** @} */ +GIT_END_DECL +#endif diff --git a/git2/include/git2/reflog.h b/git2/include/git2/reflog.h index f490e29de..447915ef8 100644 --- a/git2/include/git2/reflog.h +++ b/git2/include/git2/reflog.h @@ -23,6 +23,10 @@ GIT_BEGIN_DECL /** * Read the reflog for the given reference * + * If there is no reflog file for the given + * reference yet, an empty reflog object will + * be returned. + * * The reflog must be freed manually by using * git_reflog_free(). * @@ -33,26 +37,32 @@ GIT_BEGIN_DECL GIT_EXTERN(int) git_reflog_read(git_reflog **reflog, git_reference *ref); /** - * Write a new reflog for the given reference + * Write an existing in-memory reflog object back to disk + * using an atomic file lock. * - * If there is no reflog file for the given - * reference yet, it will be created. - * - * `oid_old` may be NULL in case it's a new reference. + * @param reflog an existing reflog object + * @return 0 or an error code + */ +GIT_EXTERN(int) git_reflog_write(git_reflog *reflog); + +/** + * Add a new entry to the reflog. * * `msg` is optional and can be NULL. * - * @param ref the changed reference - * @param oid_old the OID the reference was pointing to + * @param reflog an existing reflog object + * @param new_oid 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_write(git_reference *ref, const git_oid *oid_old, const git_signature *committer, const char *msg); +GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_signature *committer, const char *msg); /** * Rename the reflog for the given reference * + * The reflog to be renamed is expected to already exist + * * @param ref the reference * @param new_name the new name of the reference * @return 0 or an error code @@ -82,7 +92,27 @@ GIT_EXTERN(unsigned int) git_reflog_entrycount(git_reflog *reflog); * @param idx the position to lookup * @return the entry; NULL if not found */ -GIT_EXTERN(const git_reflog_entry *) git_reflog_entry_byindex(git_reflog *reflog, unsigned int idx); +GIT_EXTERN(const git_reflog_entry *) git_reflog_entry_byindex(git_reflog *reflog, size_t idx); + +/** + * Remove an entry from the reflog by its index + * + * To ensure there's no gap in the log history, set the `rewrite_previosu_entry` to 1. + * When deleting entry `n`, member old_oid of entry `n-1` (if any) will be updated with + * the value of memeber new_oid of entry `n+1`. + * + * @param reflog a previously loaded reflog. + * + * @param idx the position of the entry to remove. + * + * @param rewrite_previous_entry 1 to rewrite the history; 0 otherwise. + * + * @return 0 on success or an error code. + */ +GIT_EXTERN(int) git_reflog_drop( + git_reflog *reflog, + unsigned int idx, + int rewrite_previous_entry); /** * Get the old oid diff --git a/git2/include/git2/refs.h b/git2/include/git2/refs.h index 882e32769..001c2bcc7 100644 --- a/git2/include/git2/refs.h +++ b/git2/include/git2/refs.h @@ -10,6 +10,7 @@ #include "common.h" #include "types.h" #include "oid.h" +#include "strarray.h" /** * @file git2/refs.h @@ -124,7 +125,7 @@ GIT_EXTERN(const char *) git_reference_name(git_reference *ref); /** * Resolve a symbolic reference * - * Thie method iteratively peels a symbolic reference + * This method iteratively peels a symbolic reference * until it resolves to a direct reference to an OID. * * The peeled reference is returned in the `resolved_ref` @@ -258,7 +259,6 @@ GIT_EXTERN(int) git_reference_packall(git_repository *repo); */ GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo, unsigned int list_flags); - /** * Perform an operation on each reference in the repository * @@ -269,14 +269,15 @@ GIT_EXTERN(int) git_reference_list(git_strarray *array, git_repository *repo, un * * The `callback` function will be called for each of the references * in the repository, and will receive the name of the reference and - * the `payload` value passed to this method. + * the `payload` value passed to this method. Returning a non-zero + * value from the callback will terminate the iteration. * * @param repo Repository where to find the refs * @param list_flags Filtering flags for the reference * listing. * @param callback Function which will be called for every listed ref * @param payload Additional data to pass to the callback - * @return 0 or an error code + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_reference_foreach(git_repository *repo, unsigned int list_flags, int (*callback)(const char *, void *), void *payload); @@ -293,7 +294,7 @@ GIT_EXTERN(int) git_reference_is_packed(git_reference *ref); * * Reference pointers may become outdated if the Git * repository is accessed simultaneously by other clients - * whilt the library is open. + * while the library is open. * * This method forces a reload of the reference from disk, * to ensure that the provided information is still @@ -324,6 +325,145 @@ GIT_EXTERN(void) git_reference_free(git_reference *ref); */ GIT_EXTERN(int) git_reference_cmp(git_reference *ref1, git_reference *ref2); +/** + * Loop over all the references and issue a callback for each one + * which name matches the given glob pattern. + * + * The processed references may be filtered by type, or using + * a bitwise OR of several types. Use the magic value + * `GIT_REF_LISTALL` to obtain all references, including + * packed ones. + * + * @param repo Repository where to find the references. + * + * @param glob Glob pattern references should match. + * + * @param list_flags Filtering flags for the reference + * listing. + * + * @param callback Callback to invoke per found reference. + * + * @param payload Extra parameter to callback function. + * + * @return 0 or an error code. + */ +GIT_EXTERN(int) git_reference_foreach_glob( + git_repository *repo, + const char *glob, + unsigned int list_flags, + int (*callback)( + const char *reference_name, + void *payload), + void *payload +); + +/** + * Check if a reflog exists for the specified reference. + * + * @param ref A git reference + * + * @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); + +/** + * Check if a reference is a local branch. + * + * @param ref A git reference + * + * @return 1 when the reference lives in the refs/heads + * namespace; 0 otherwise. + */ +GIT_EXTERN(int) git_reference_is_branch(git_reference *ref); + +/** + * Check if a reference is a remote tracking branch + * + * @param ref A git reference + * + * @return 1 when the reference lives in the refs/remotes + * namespace; 0 otherwise. + */ +GIT_EXTERN(int) git_reference_is_remote(git_reference *ref); + +enum { + GIT_REF_FORMAT_NORMAL = 0, + + /** + * Control whether one-level refnames are accepted + * (i.e., refnames that do not contain multiple /-separated + * components). Those are expected to be written only using + * uppercase letters and underscore (FETCH_HEAD, ...) + */ + GIT_REF_FORMAT_ALLOW_ONELEVEL = (1 << 0), + + /** + * Interpret the provided name as a reference pattern for a + * refspec (as used with remote repositories). If this option + * is enabled, the name is allowed to contain a single * () + * in place of a one full pathname component + * (e.g., foo//bar but not foo/bar). + */ + GIT_REF_FORMAT_REFSPEC_PATTERN = (1 << 1), +}; + +/** + * Normalize the reference name by removing any leading + * slash (/) characters and collapsing runs of adjacent slashes + * between name components into a single slash. + * + * Once normalized, if the reference name is valid, it will be + * returned in the user allocated buffer. + * + * @param buffer_out The user allocated buffer where the + * normalized name will be stored. + * + * @param buffer_size buffer_out size + * + * @param name name to be checked. + * + * @param flags Flags to determine the options to be applied while + * checking the validatity of the name. + * + * @return 0 or an error code. + */ +GIT_EXTERN(int) git_reference_normalize_name( + char *buffer_out, + size_t buffer_size, + const char *name, + unsigned int flags); + +/** + * Recursively peel an reference until an object of the + * specified type is met. + * + * The retrieved `peeled` object is owned by the repository + * and should be closed with the `git_object_free` method. + * + * If you pass `GIT_OBJ_ANY` as the target type, then the object + * will be peeled until a non-tag object is met. + * + * @param peeled Pointer to the peeled git_object + * @param ref The reference to be processed + * @param target_type The type of the requested object + * @return 0 or an error code + */ +GIT_EXTERN(int) git_reference_peel( + git_object **out, + git_reference *ref, + git_otype type); + +/** + * Ensure the reference name is well-formed. + * + * @param refname name to be checked. + * + * @return 1 if the reference name is acceptable; 0 if it isn't + */ +GIT_EXTERN(int) git_reference_is_valid_name( + const char *refname); + /** @} */ GIT_END_DECL #endif diff --git a/git2/include/git2/refspec.h b/git2/include/git2/refspec.h index c0a8eabfe..1100e9022 100644 --- a/git2/include/git2/refspec.h +++ b/git2/include/git2/refspec.h @@ -35,6 +35,14 @@ GIT_EXTERN(const char *) git_refspec_src(const git_refspec *refspec); */ GIT_EXTERN(const char *) git_refspec_dst(const git_refspec *refspec); +/** + * Get the force update setting + * + * @param refspec the refspec + * @return 1 if force update has been set, 0 otherwise + */ +GIT_EXTERN(int) git_refspec_force(const git_refspec *refspec); + /** * Check if a refspec's source descriptor matches a reference * diff --git a/git2/include/git2/remote.h b/git2/include/git2/remote.h index 865dfef04..ad5c38902 100644 --- a/git2/include/git2/remote.h +++ b/git2/include/git2/remote.h @@ -12,6 +12,7 @@ #include "refspec.h" #include "net.h" #include "indexer.h" +#include "strarray.h" /** * @file git2/remote.h @@ -37,7 +38,7 @@ GIT_BEGIN_DECL * this when you have a URL instead of a remote's name. * * @param out pointer to the new remote object - * @param repo the associtated repository + * @param repo the associated repository * @param name the remote's name * @param url the remote repository's URL * @param fetch the fetch refspec to use for this remote @@ -79,6 +80,36 @@ GIT_EXTERN(const char *) git_remote_name(git_remote *remote); */ GIT_EXTERN(const char *) git_remote_url(git_remote *remote); +/** + * Get the remote's url for pushing + * + * @param remote the remote + * @return a pointer to the url or NULL if no special url for pushing is set + */ +GIT_EXTERN(const char *) git_remote_pushurl(git_remote *remote); + +/** + * Set the remote's url + * + * Existing connections will not be updated. + * + * @param remote the remote + * @param url the url to set + * @return 0 or an error value + */ +GIT_EXTERN(int) git_remote_set_url(git_remote *remote, const char* url); + +/** + * Set the remote's url for pushing + * + * Existing connections will not be updated. + * + * @param remote the remote + * @param url the url to set or NULL to clear the pushurl + * @return 0 or an error value + */ +GIT_EXTERN(int) git_remote_set_pushurl(git_remote *remote, const char* url); + /** * Set the remote's fetch refspec * @@ -100,7 +131,7 @@ GIT_EXTERN(const git_refspec *) git_remote_fetchspec(git_remote *remote); * Set the remote's push refspec * * @param remote the remote - * @apram spec the new push refspec + * @param spec the new push refspec * @return 0 or an error value */ GIT_EXTERN(int) git_remote_set_pushspec(git_remote *remote, const char *spec); @@ -133,9 +164,12 @@ GIT_EXTERN(int) git_remote_connect(git_remote *remote, int direction); * The remote (or more exactly its transport) must be connected. The * memory belongs to the remote. * + * If you a return a non-zero value from the callback, this will stop + * looping over the refs. + * * @param refs where to store the refs * @param remote the remote - * @return 0 or an error code + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload); @@ -149,10 +183,16 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void * filename will be NULL and the function will return success. * * @param remote the remote to download from - * @param filename where to store the temproray filename + * @param progress_cb function to call with progress information. Be aware that + * this is called inline with network and indexing operations, so performance + * may be affected. + * @param progress_payload payload for the progress callback * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_download(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats); +GIT_EXTERN(int) git_remote_download( + git_remote *remote, + git_transfer_progress_callback progress_cb, + void *progress_payload); /** * Check whether the remote is connected @@ -164,6 +204,14 @@ GIT_EXTERN(int) git_remote_download(git_remote *remote, git_off_t *bytes, git_in */ GIT_EXTERN(int) git_remote_connected(git_remote *remote); +/** + * Cancel the operation + * + * At certain points in its operation, the network code checks whether + * the operation has been cancelled and if so stops the operation. + */ +GIT_EXTERN(void) git_remote_stop(git_remote *remote); + /** * Disconnect from the remote * @@ -190,12 +238,12 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote); * @param remote the remote to update * @param cb callback to run on each ref update. 'a' is the old value, 'b' is then new value */ -GIT_EXTERN(int) git_remote_update_tips(git_remote *remote, int (*cb)(const char *refname, const git_oid *a, const git_oid *b)); +GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); /** * Return whether a string is a valid remote URL * - * @param tranport the url to check + * @param url the url to check * @param 1 if the url is valid, 0 otherwise */ GIT_EXTERN(int) git_remote_valid_url(const char *url); @@ -229,6 +277,95 @@ GIT_EXTERN(int) git_remote_list(git_strarray *remotes_list, git_repository *repo */ GIT_EXTERN(int) git_remote_add(git_remote **out, git_repository *repo, const char *name, const char *url); +/** + * Choose whether to check the server's certificate (applies to HTTPS only) + * + * @param remote the remote to configure + * @param check whether to check the server's certificate (defaults to yes) + */ + +GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check); + +/** + * Argument to the completion callback which tells it which operation + * finished. + */ +typedef enum git_remote_completion_type { + GIT_REMOTE_COMPLETION_DOWNLOAD, + GIT_REMOTE_COMPLETION_INDEXING, + GIT_REMOTE_COMPLETION_ERROR, +} git_remote_completion_type; + +/** + * The callback settings structure + * + * Set the calbacks to be called by the remote. + */ +struct git_remote_callbacks { + void (*progress)(const char *str, int len, void *data); + int (*completion)(git_remote_completion_type type, void *data); + int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data); + void *data; +}; + +/** + * Set the callbacks for a remote + * + * Note that the remote keeps its own copy of the data and you need to + * call this function again if you want to change the callbacks. + * + * @param remote the remote to configure + * @param callbacks a pointer to the user's callback settings + */ +GIT_EXTERN(void) git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks); + +/** + * Get the statistics structure that is filled in by the fetch operation. + */ +GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote); + +enum { + GIT_REMOTE_DOWNLOAD_TAGS_UNSET, + GIT_REMOTE_DOWNLOAD_TAGS_NONE, + GIT_REMOTE_DOWNLOAD_TAGS_AUTO, + GIT_REMOTE_DOWNLOAD_TAGS_ALL +}; + +/** + * Retrieve the tag auto-follow setting + * + * @param remote the remote to query + * @return the auto-follow setting + */ +GIT_EXTERN(int) git_remote_autotag(git_remote *remote); + +/** + * Set the tag auto-follow setting + * + * @param remote the remote to configure + * @param value a GIT_REMOTE_DOWNLOAD_TAGS value + */ +GIT_EXTERN(void) git_remote_set_autotag(git_remote *remote, int value); + +/** + * Give the remote a new name + * + * All remote-tracking branches and configuration settings + * for the remote are updated. + * + * @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 or an error code + */ +GIT_EXTERN(int) git_remote_rename( + git_remote *remote, + const char *new_name, + int (*callback)(const char *problematic_refspec, void *payload), + void *payload); + /** @} */ GIT_END_DECL #endif diff --git a/git2/include/git2/repository.h b/git2/include/git2/repository.h index 3949438cf..d72431538 100644 --- a/git2/include/git2/repository.h +++ b/git2/include/git2/repository.h @@ -35,6 +35,19 @@ GIT_BEGIN_DECL */ GIT_EXTERN(int) git_repository_open(git_repository **repository, const char *path); +/** + * Create a "fake" repository to wrap an object database + * + * Create a repository object to wrap an object database to be used + * with the API when all you have is an object database. This doesn't + * have any paths associated with it, so use with care. + * + * @param repository pointer to the repo + * @param odb the object database to wrap + * @return 0 or an error code + */ +GIT_EXTERN(int) git_repository_wrap_odb(git_repository **repository, git_odb *odb); + /** * Look for a git repository and copy its path in the given buffer. * The lookup start from base_path and walk across parent directories @@ -70,6 +83,18 @@ GIT_EXTERN(int) git_repository_discover( int across_fs, const char *ceiling_dirs); +/** + * Option flags for `git_repository_open_ext`. + * + * * GIT_REPOSITORY_OPEN_NO_SEARCH - Only open the repository if it can be + * immediately found in the start_path. Do not walk up from the + * start_path looking at parent directories. + * * GIT_REPOSITORY_OPEN_CROSS_FS - Unless this flag is set, open will not + * continue searching across filesystem boundaries (i.e. when `st_dev` + * changes from the `stat` system call). (E.g. Searching in a user's home + * directory "/home/user/source/" will not return "/.git/" as the found + * repo if "/" is a different filesystem than "/home".) + */ enum { GIT_REPOSITORY_OPEN_NO_SEARCH = (1 << 0), GIT_REPOSITORY_OPEN_CROSS_FS = (1 << 1), @@ -77,6 +102,20 @@ enum { /** * Find and open a repository with extended controls. + * + * @param repo_out Pointer to the repo which will be opened. This can + * actually be NULL if you only want to use the error code to + * see if a repo at this path could be opened. + * @param start_path Path to open as git repository. If the flags + * permit "searching", then this can be a path to a subdirectory + * inside the working directory of the repository. + * @param flags A combination of the GIT_REPOSITORY_OPEN flags above. + * @param ceiling_dirs A GIT_PATH_LIST_SEPARATOR delimited list of path + * prefixes at which the search for a containing repository should + * terminate. + * @return 0 on success, GIT_ENOTFOUND if no repository could be found, + * or -1 if there was a repository but open failed for some reason + * (such as repo corruption or system errors). */ GIT_EXTERN(int) git_repository_open_ext( git_repository **repo, @@ -105,13 +144,127 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo); * * @param repo_out pointer to the repo which will be created or reinitialized * @param path the path to the repository - * @param is_bare if true, a Git repository without a working directory is created - * at the pointed path. If false, provided path will be considered as the working - * directory into which the .git directory will be created. + * @param is_bare if true, a Git repository without a working directory is + * created at the pointed path. If false, provided path will be + * considered as the working directory into which the .git directory + * will be created. * * @return 0 or an error code */ -GIT_EXTERN(int) git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare); +GIT_EXTERN(int) git_repository_init( + git_repository **repo_out, + const char *path, + unsigned is_bare); + +/** + * Option flags for `git_repository_init_ext`. + * + * These flags configure extra behaviors to `git_repository_init_ext`. + * In every case, the default behavior is the zero value (i.e. flag is + * not set). Just OR the flag values together for the `flags` parameter + * when initializing a new repo. Details of individual values are: + * + * * BARE - Create a bare repository with no working directory. + * * NO_REINIT - Return an EEXISTS error if the repo_path appears to + * already be an git repository. + * * NO_DOTGIT_DIR - Normally a "/.git/" will be appended to the repo + * path for non-bare repos (if it is not already there), but + * passing this flag prevents that behavior. + * * MKDIR - Make the repo_path (and workdir_path) as needed. Init is + * always willing to create the ".git" directory even without this + * flag. This flag tells init to create the trailing component of + * the repo and workdir paths as needed. + * * MKPATH - Recursively make all components of the repo and workdir + * paths as necessary. + * * EXTERNAL_TEMPLATE - libgit2 normally uses internal templates to + * initialize a new repo. This flags enables external templates, + * looking the "template_path" from the options if set, or the + * `init.templatedir` global config if not, or falling back on + * "/usr/share/git-core/templates" if it exists. + */ +enum { + GIT_REPOSITORY_INIT_BARE = (1u << 0), + GIT_REPOSITORY_INIT_NO_REINIT = (1u << 1), + GIT_REPOSITORY_INIT_NO_DOTGIT_DIR = (1u << 2), + GIT_REPOSITORY_INIT_MKDIR = (1u << 3), + GIT_REPOSITORY_INIT_MKPATH = (1u << 4), + GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE = (1u << 5), +}; + +/** + * Mode options for `git_repository_init_ext`. + * + * Set the mode field of the `git_repository_init_options` structure + * either to the custom mode that you would like, or to one of the + * following modes: + * + * * SHARED_UMASK - Use permissions configured by umask - the default. + * * SHARED_GROUP - Use "--shared=group" behavior, chmod'ing the new repo + * to be group writable and "g+sx" for sticky group assignment. + * * SHARED_ALL - Use "--shared=all" behavior, adding world readability. + * * Anything else - Set to custom value. + */ +enum { + GIT_REPOSITORY_INIT_SHARED_UMASK = 0, + GIT_REPOSITORY_INIT_SHARED_GROUP = 0002775, + GIT_REPOSITORY_INIT_SHARED_ALL = 0002777, +}; + +/** + * Extended options structure for `git_repository_init_ext`. + * + * This contains extra options for `git_repository_init_ext` that enable + * additional initialization features. The fields are: + * + * * flags - Combination of GIT_REPOSITORY_INIT flags above. + * * mode - Set to one of the standard GIT_REPOSITORY_INIT_SHARED_... + * constants above, or to a custom value that you would like. + * * workdir_path - The path to the working dir or NULL for default (i.e. + * repo_path parent on non-bare repos). IF THIS IS RELATIVE PATH, + * IT WILL BE EVALUATED RELATIVE TO THE REPO_PATH. If this is not + * the "natural" working directory, a .git gitlink file will be + * created here linking to the repo_path. + * * description - If set, this will be used to initialize the "description" + * file in the repository, instead of using the template content. + * * template_path - When GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE is set, + * this contains the path to use for the template directory. If + * this is NULL, the config or default directory options will be + * used instead. + * * initial_head - The name of the head to point HEAD at. If NULL, then + * this will be treated as "master" and the HEAD ref will be set + * to "refs/heads/master". If this begins with "refs/" it will be + * used verbatim; otherwise "refs/heads/" will be prefixed. + * * origin_url - If this is non-NULL, then after the rest of the + * repository initialization is completed, an "origin" remote + * will be added pointing to this URL. + */ +typedef struct { + uint32_t flags; + uint32_t mode; + const char *workdir_path; + const char *description; + const char *template_path; + const char *initial_head; + const char *origin_url; +} git_repository_init_options; + +/** + * Create a new Git repository in the given folder with extended controls. + * + * This will initialize a new git repository (creating the repo_path + * if requested by flags) and working directory as needed. It will + * auto-detect the case sensitivity of the file system and if the + * file system supports file mode bits correctly. + * + * @param repo_out Pointer to the repo which will be created or reinitialized. + * @param repo_path The path to the repository. + * @param opts Pointer to git_repository_init_options struct. + * @return 0 or an error code on failure. + */ +GIT_EXTERN(int) git_repository_init_ext( + git_repository **repo_out, + const char *repo_path, + git_repository_init_options *opts); /** * Retrieve and resolve the reference pointed at by HEAD. @@ -119,7 +272,8 @@ GIT_EXTERN(int) git_repository_init(git_repository **repo_out, const char *path, * @param head_out pointer to the reference which will be retrieved * @param repo a repository object * - * @return 0 on success; error code otherwise + * @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing + * branch, an error code otherwise */ GIT_EXTERN(int) git_repository_head(git_reference **head_out, git_repository *repo); @@ -130,7 +284,7 @@ GIT_EXTERN(int) git_repository_head(git_reference **head_out, git_repository *re * instead of a branch. * * @param repo Repo to test - * @return 1 if HEAD is detached, 0 if i'ts not; error code if there + * @return 1 if HEAD is detached, 0 if it's not; error code if there * was an error. */ GIT_EXTERN(int) git_repository_head_detached(git_repository *repo); @@ -143,7 +297,7 @@ GIT_EXTERN(int) git_repository_head_detached(git_repository *repo); * * @param repo Repo to test * @return 1 if the current branch is an orphan, 0 if it's not; error - * code if therewas an error + * code if there was an error */ GIT_EXTERN(int) git_repository_head_orphan(git_repository *repo); @@ -194,9 +348,12 @@ GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo); * * @param repo A repository object * @param workdir The path to a working directory + * @param update_gitlink Create/update gitlink in workdir and set config + * "core.worktree" (if workdir is not the parent of the .git directory) * @return 0, or an error code */ -GIT_EXTERN(int) git_repository_set_workdir(git_repository *repo, const char *workdir); +GIT_EXTERN(int) git_repository_set_workdir( + git_repository *repo, const char *workdir, int update_gitlink); /** * Check if a repository is bare @@ -299,6 +456,135 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo); */ GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index); +/** + * Retrieve git's prepared message + * + * Operations such as git revert/cherry-pick/merge with the -n option + * stop just short of creating a commit with the changes and save + * their prepared message in .git/MERGE_MSG so the next git-commit + * execution can present it to the user for them to amend if they + * wish. + * + * Use this function to get the contents of this file. Don't forget to + * remove the file after you create the commit. + * + * @param buffer Buffer to write data into or NULL to just read required size + * @param len Length of buffer in bytes + * @param repo Repository to read prepared message from + * @return Bytes written to buffer, GIT_ENOTFOUND if no message, or -1 on error + */ +GIT_EXTERN(int) git_repository_message(char *buffer, size_t len, git_repository *repo); + +/** + * Remove git's prepared message. + * + * Remove the message that `git_repository_message` retrieves. + */ +GIT_EXTERN(int) git_repository_message_remove(git_repository *repo); + +/** + * Calculate hash of file using repository filtering rules. + * + * If you simply want to calculate the hash of a file on disk with no filters, + * you can just use the `git_odb_hashfile()` API. However, if you want to + * 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. + * + * @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 + * repository is not NULL, this can be a relative path. + * @param type The object type to hash as (e.g. GIT_OBJ_BLOB) + * @param as_path The path to use to look up filtering rules. If this is + * 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. + */ +GIT_EXTERN(int) git_repository_hashfile( + git_oid *out, + git_repository *repo, + const char *path, + git_otype type, + const char *as_path); + +/** + * Make the repository HEAD point to the specified reference. + * + * If the provided reference points to a Tree or a Blob, the HEAD is + * unaltered and -1 is returned. + * + * If the provided reference points to a branch, the HEAD will point + * to that branch, staying attached, or become attached if it isn't yet. + * If the branch doesn't exist yet, no error will be return. The HEAD + * will then be attached to an unborn branch. + * + * Otherwise, the HEAD will be detached and will directly point to + * the Commit. + * + * @param repo Repository pointer + * @param refname Canonical name of the reference the HEAD should point at + * @return 0 on success, or an error code + */ +GIT_EXTERN(int) git_repository_set_head( + git_repository* repo, + const char* refname); + +/** + * Make the repository HEAD directly point to the Commit. + * + * If the provided committish cannot be found in the repository, the HEAD + * is unaltered and GIT_ENOTFOUND is returned. + * + * If the provided commitish cannot be peeled into a commit, the HEAD + * is unaltered and -1 is returned. + * + * Otherwise, the HEAD will eventually be detached and will directly point to + * the peeled Commit. + * + * @param repo Repository pointer + * @param commitish Object id of the Commit the HEAD should point to + * @return 0 on success, or an error code + */ +GIT_EXTERN(int) git_repository_set_head_detached( + git_repository* repo, + const git_oid* commitish); + +/** + * Detach the HEAD. + * + * If the HEAD is already detached and points to a Commit, 0 is returned. + * + * If the HEAD is already detached and points to a Tag, the HEAD is + * updated into making it point to the peeled Commit, and 0 is returned. + * + * If the HEAD is already detached and points to a non commitish, the HEAD is + * unaletered, and -1 is returned. + * + * Otherwise, the HEAD will be detached and point to the peeled Commit. + * + * @param repo Repository pointer + * @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing + * branch or an error code + */ +GIT_EXTERN(int) git_repository_detach_head( + git_repository* repo); + +typedef enum { + GIT_REPOSITORY_STATE_NONE, + GIT_REPOSITORY_STATE_MERGE, + GIT_REPOSITORY_STATE_REVERT, + GIT_REPOSITORY_STATE_CHERRY_PICK, +} git_repository_state_t; + +/** + * Determines the status of a git repository - ie, whether an operation + * (merge, cherry-pick, etc) is in progress. + * + * @param repo Repository pointer + * @return The state of the repository + */ +GIT_EXTERN(int) git_repository_state(git_repository *repo); + /** @} */ GIT_END_DECL #endif diff --git a/git2/include/git2/reset.h b/git2/include/git2/reset.h new file mode 100644 index 000000000..cdcfb7671 --- /dev/null +++ b/git2/include/git2/reset.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * 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_reset_h__ +#define INCLUDE_git_reset_h__ + +/** + * @file git2/reset.h + * @brief Git reset management routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Sets the current head to the specified commit oid and optionally + * resets the index and working tree to match. + * + * When specifying a Soft kind of reset, the head will be moved to the commit. + * + * Specifying a Mixed kind of reset will trigger a Soft reset and the index will + * be replaced with the content of the commit tree. + * + * Specifying a Hard kind of reset will trigger a Mixed reset and the working + * directory will be replaced with the content of the index. + * + * TODO: Implement remaining kinds of resets. + * + * @param repo Repository where to perform the reset operation. + * + * @param target Object to which the Head should be moved to. This object + * must belong to the given `repo` and can either be a git_commit or a + * git_tag. When a git_tag is being passed, it should be dereferencable + * to a git_commit which oid will be used as the target of the branch. + * + * @param reset_type Kind of reset operation to perform. + * + * @return GIT_SUCCESS or an error code + */ +GIT_EXTERN(int) git_reset(git_repository *repo, git_object *target, git_reset_type reset_type); + +/** @} */ +GIT_END_DECL +#endif diff --git a/git2/include/git2/revparse.h b/git2/include/git2/revparse.h new file mode 100644 index 000000000..4567027e5 --- /dev/null +++ b/git2/include/git2/revparse.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 the libgit2 contributors + * + * 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_revparse_h__ +#define INCLUDE_git_revparse_h__ + +#include "common.h" +#include "types.h" + + +/** + * @file git2/revparse.h + * @brief Git revision parsing routines + * @defgroup git_revparse Git revision parsing routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Find an object, as specified by a revision string. See `man gitrevisions`, or the documentation + * for `git rev-parse` for information on the syntax accepted. + * + * @param out pointer to output object + * @param repo the repository to search in + * @param spec the textual specification for an object + * @return on success, GIT_ERROR otherwise (use git_error_last for information about the error) + */ +GIT_EXTERN(int) git_revparse_single(git_object **out, git_repository *repo, const char *spec); + +/** @} */ +GIT_END_DECL +#endif diff --git a/git2/include/git2/revwalk.h b/git2/include/git2/revwalk.h index aac6fb7c2..0a85a4c60 100644 --- a/git2/include/git2/revwalk.h +++ b/git2/include/git2/revwalk.h @@ -104,10 +104,10 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *oid); /** * Push matching references * - * The OIDs pinted to by the references that match the given glob + * The OIDs pointed to by the references that match the given glob * pattern will be pushed to the revision walker. * - * A leading 'refs/' is implied it not present as well as a trailing + * A leading 'refs/' is implied if not present as well as a trailing * '/ *' if the glob lacks '?', '*' or '['. * * @param walk the walker being used for the traversal @@ -142,11 +142,11 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *oid); /** * Hide matching references. * - * The OIDs pinted to by the references that match the given glob + * The OIDs pointed to by the references that match the given glob * pattern and their ancestors will be hidden from the output on the * revision walk. * - * A leading 'refs/' is implied it not present as well as a trailing + * A leading 'refs/' is implied if not present as well as a trailing * '/ *' if the glob lacks '?', '*' or '['. * * @param walk the walker being used for the traversal @@ -169,7 +169,7 @@ GIT_EXTERN(int) git_revwalk_hide_head(git_revwalk *walk); * The reference must point to a commit. * * @param walk the walker being used for the traversal - * @param refname the referece to push + * @param refname the reference to push * @return 0 or an error code */ GIT_EXTERN(int) git_revwalk_push_ref(git_revwalk *walk, const char *refname); @@ -180,7 +180,7 @@ GIT_EXTERN(int) git_revwalk_push_ref(git_revwalk *walk, const char *refname); * The reference must point to a commit. * * @param walk the walker being used for the traversal - * @param refname the referece to hide + * @param refname the reference to hide * @return 0 or an error code */ GIT_EXTERN(int) git_revwalk_hide_ref(git_revwalk *walk, const char *refname); @@ -201,7 +201,7 @@ GIT_EXTERN(int) git_revwalk_hide_ref(git_revwalk *walk, const char *refname); * @param oid Pointer where to store the oid of the next commit * @param walk the walker to pop the commit from. * @return 0 if the next commit was found; - * GIT_REVWALKOVER if there are no commits left to iterate + * GIT_ITEROVER if there are no commits left to iterate */ GIT_EXTERN(int) git_revwalk_next(git_oid *oid, git_revwalk *walk); diff --git a/git2/include/git2/signature.h b/git2/include/git2/signature.h index cbf94269f..cdbe67879 100644 --- a/git2/include/git2/signature.h +++ b/git2/include/git2/signature.h @@ -23,6 +23,9 @@ GIT_BEGIN_DECL * Create a new action signature. The signature must be freed * manually or using git_signature_free * + * Note: angle brackets ('<' and '>') characters are not allowed + * to be used in either the `name` or the `email` parameter. + * * @param sig_out new signature, in case of error NULL * @param name name of the person * @param email email of the person diff --git a/git2/include/git2/status.h b/git2/include/git2/status.h index 6a424dfd6..979e6e4ff 100644 --- a/git2/include/git2/status.h +++ b/git2/include/git2/status.h @@ -19,30 +19,33 @@ */ GIT_BEGIN_DECL -enum { - GIT_STATUS_CURRENT = 0, +typedef enum { + GIT_STATUS_CURRENT = 0, - GIT_STATUS_INDEX_NEW = (1 << 0), - GIT_STATUS_INDEX_MODIFIED = (1 << 1), - GIT_STATUS_INDEX_DELETED = (1 << 2), + GIT_STATUS_INDEX_NEW = (1u << 0), + GIT_STATUS_INDEX_MODIFIED = (1u << 1), + GIT_STATUS_INDEX_DELETED = (1u << 2), + GIT_STATUS_INDEX_RENAMED = (1u << 3), + GIT_STATUS_INDEX_TYPECHANGE = (1u << 4), - GIT_STATUS_WT_NEW = (1 << 3), - GIT_STATUS_WT_MODIFIED = (1 << 4), - GIT_STATUS_WT_DELETED = (1 << 5), + GIT_STATUS_WT_NEW = (1u << 7), + GIT_STATUS_WT_MODIFIED = (1u << 8), + GIT_STATUS_WT_DELETED = (1u << 9), + GIT_STATUS_WT_TYPECHANGE = (1u << 10), - GIT_STATUS_IGNORED = (1 << 6), -}; + GIT_STATUS_IGNORED = (1u << 14), +} git_status_t; /** * Gather file statuses and run a callback for each one. * * The callback is passed the path of the file, the status and the data * pointer passed to this function. If the callback returns something other - * than 0, this function will return that value. + * than 0, this function will stop looping and return GIT_EUSER. * * @param repo a repository object * @param callback the function to call on each file - * @return 0 on success or the return value of the callback that was non-zero + * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_status_foreach( git_repository *repo, @@ -96,14 +99,17 @@ typedef enum { * the top-level directory will be included (with a trailing * slash on the entry name). Given this flag, the directory * itself will not be included, but all the files in it will. + * - GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH indicates that the given + * path will be treated as a literal path, and not as a pathspec. */ enum { GIT_STATUS_OPT_INCLUDE_UNTRACKED = (1 << 0), GIT_STATUS_OPT_INCLUDE_IGNORED = (1 << 1), GIT_STATUS_OPT_INCLUDE_UNMODIFIED = (1 << 2), - GIT_STATUS_OPT_EXCLUDE_SUBMODULED = (1 << 3), + GIT_STATUS_OPT_EXCLUDE_SUBMODULES = (1 << 3), GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = (1 << 4), + GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH = (1 << 5), }; /** @@ -143,10 +149,12 @@ GIT_EXTERN(int) git_status_file( /** * Test if the ignore rules apply to a given file. * - * This function simply checks the ignore rules to see if they would apply - * to the given file. Unlike git_status_file(), this indicates if the file - * would be ignored regardless of whether the file is already in the index - * or in the repository. + * This function checks the ignore rules to see if they would apply to the + * given file. This indicates if the file would be ignored regardless of + * whether the file is already in the index or commited to the repository. + * + * One way to think of this is if you were to do "git add ." on the + * directory containing the file, would it be added or not? * * @param ignored boolean returning 0 if the file is not ignored, 1 if it is * @param repo a repository object diff --git a/git2/include/git2/strarray.h b/git2/include/git2/strarray.h new file mode 100644 index 000000000..f6092fa9c --- /dev/null +++ b/git2/include/git2/strarray.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * 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_strarray_h__ +#define INCLUDE_git_strarray_h__ + +#include "common.h" + +/** + * @file git2/strarray.h + * @brief Git string array routines + * @defgroup git_strarray Git string array routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** Array of strings */ +typedef struct _git_strarray git_strarray; +struct _git_strarray { + char **strings; + size_t count; +}; + +/** + * Close a string array object + * + * This method must always be called once a git_strarray is no + * longer needed, otherwise memory will leak. + * + * @param array array to close + */ +GIT_EXTERN(void) git_strarray_free(git_strarray *array); + +/** + * Copy a string array object from source to target. + * + * Note: target is overwritten and hence should be empty, + * otherwise its contents are leaked. + * + * @param tgt target + * @param src source + */ +GIT_EXTERN(int) git_strarray_copy(git_strarray *tgt, const git_strarray *src); + + +/** @} */ +GIT_END_DECL + +#endif + diff --git a/git2/include/git2/submodule.h b/git2/include/git2/submodule.h index 930168275..b00fad2d4 100644 --- a/git2/include/git2/submodule.h +++ b/git2/include/git2/submodule.h @@ -20,54 +20,160 @@ */ GIT_BEGIN_DECL +/** + * Opaque structure representing a submodule. + * + * Submodule support in libgit2 builds a list of known submodules and keeps + * it in the repository. The list is built from the .gitmodules file, the + * .git/config file, the index, and the HEAD tree. Items in the working + * directory that look like submodules (i.e. a git repo) but are not + * mentioned in those places won't be tracked. + */ +typedef struct git_submodule git_submodule; + +/** + * Values that could be specified for the update rule of a submodule. + * + * Use the DEFAULT value if you have altered the update value via + * `git_submodule_set_update()` and wish to reset to the original default. + */ typedef enum { + GIT_SUBMODULE_UPDATE_DEFAULT = -1, GIT_SUBMODULE_UPDATE_CHECKOUT = 0, GIT_SUBMODULE_UPDATE_REBASE = 1, - GIT_SUBMODULE_UPDATE_MERGE = 2 + GIT_SUBMODULE_UPDATE_MERGE = 2, + GIT_SUBMODULE_UPDATE_NONE = 3 } git_submodule_update_t; +/** + * Values that could be specified for how closely to examine the + * working directory when getting submodule status. + * + * Use the DEFUALT value if you have altered the ignore value via + * `git_submodule_set_ignore()` and wish to reset to the original value. + */ typedef enum { - GIT_SUBMODULE_IGNORE_ALL = 0, /* never dirty */ - GIT_SUBMODULE_IGNORE_DIRTY = 1, /* only dirty if HEAD moved */ - GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /* dirty if tracked files change */ - GIT_SUBMODULE_IGNORE_NONE = 3 /* any change or untracked == dirty */ + GIT_SUBMODULE_IGNORE_DEFAULT = -1, /* reset to default */ + GIT_SUBMODULE_IGNORE_NONE = 0, /* any change or untracked == dirty */ + GIT_SUBMODULE_IGNORE_UNTRACKED = 1, /* dirty if tracked files change */ + GIT_SUBMODULE_IGNORE_DIRTY = 2, /* only dirty if HEAD moved */ + GIT_SUBMODULE_IGNORE_ALL = 3 /* never dirty */ } git_submodule_ignore_t; /** - * Description of submodule + * Return codes for submodule status. * - * This record describes a submodule found in a repository. There - * should be an entry for every submodule found in the HEAD and for - * every submodule described in .gitmodules. The fields are as follows: + * A combination of these flags will be returned to describe the status of a + * submodule. Depending on the "ignore" property of the submodule, some of + * the flags may never be returned because they indicate changes that are + * supposed to be ignored. * - * - `name` is the name of the submodule from .gitmodules. - * - `path` is the path to the submodule from the repo working directory. - * It is almost always the same as `name`. - * - `url` is the url for the submodule. - * - `oid` is the HEAD SHA1 for the submodule. - * - `update` is a value from above - see gitmodules(5) update. - * - `ignore` is a value from above - see gitmodules(5) ignore. - * - `fetch_recurse` is 0 or 1 - see gitmodules(5) fetchRecurseSubmodules. - * - `refcount` is for internal use. + * Submodule info is contained in 4 places: the HEAD tree, the index, config + * files (both .git/config and .gitmodules), and the working directory. Any + * or all of those places might be missing information about the submodule + * depending on what state the repo is in. We consider all four places to + * build the combination of status flags. * - * If the submodule has been added to .gitmodules but not yet git added, - * then the `oid` will be zero. If the submodule has been deleted, but - * the delete has not been committed yet, then the `oid` will be set, but - * the `url` will be NULL. + * There are four values that are not really status, but give basic info + * about what sources of submodule data are available. These will be + * returned even if ignore is set to "ALL". + * + * * IN_HEAD - superproject head contains submodule + * * IN_INDEX - superproject index contains submodule + * * IN_CONFIG - superproject gitmodules has submodule + * * IN_WD - superproject workdir has submodule + * + * The following values will be returned so long as ignore is not "ALL". + * + * * INDEX_ADDED - in index, not in head + * * INDEX_DELETED - in head, not in index + * * INDEX_MODIFIED - index and head don't match + * * WD_UNINITIALIZED - workdir contains empty directory + * * WD_ADDED - in workdir, not index + * * WD_DELETED - in index, not workdir + * * WD_MODIFIED - index and workdir head don't match + * + * The following can only be returned if ignore is "NONE" or "UNTRACKED". + * + * * WD_INDEX_MODIFIED - submodule workdir index is dirty + * * WD_WD_MODIFIED - submodule workdir has modified files + * + * Lastly, the following will only be returned for ignore "NONE". + * + * * WD_UNTRACKED - wd contains untracked files */ -typedef struct { - char *name; - char *path; - char *url; - git_oid oid; /* sha1 of submodule HEAD ref or zero if not committed */ - git_submodule_update_t update; - git_submodule_ignore_t ignore; - int fetch_recurse; - int refcount; -} git_submodule; +typedef enum { + GIT_SUBMODULE_STATUS_IN_HEAD = (1u << 0), + GIT_SUBMODULE_STATUS_IN_INDEX = (1u << 1), + GIT_SUBMODULE_STATUS_IN_CONFIG = (1u << 2), + GIT_SUBMODULE_STATUS_IN_WD = (1u << 3), + GIT_SUBMODULE_STATUS_INDEX_ADDED = (1u << 4), + GIT_SUBMODULE_STATUS_INDEX_DELETED = (1u << 5), + GIT_SUBMODULE_STATUS_INDEX_MODIFIED = (1u << 6), + GIT_SUBMODULE_STATUS_WD_UNINITIALIZED = (1u << 7), + GIT_SUBMODULE_STATUS_WD_ADDED = (1u << 8), + GIT_SUBMODULE_STATUS_WD_DELETED = (1u << 9), + GIT_SUBMODULE_STATUS_WD_MODIFIED = (1u << 10), + GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED = (1u << 11), + GIT_SUBMODULE_STATUS_WD_WD_MODIFIED = (1u << 12), + GIT_SUBMODULE_STATUS_WD_UNTRACKED = (1u << 13), +} git_submodule_status_t; + +#define GIT_SUBMODULE_STATUS_IS_UNMODIFIED(S) \ + (((S) & ~(GIT_SUBMODULE_STATUS_IN_HEAD | \ + GIT_SUBMODULE_STATUS_IN_INDEX | \ + GIT_SUBMODULE_STATUS_IN_CONFIG | \ + GIT_SUBMODULE_STATUS_IN_WD)) == 0) + +#define GIT_SUBMODULE_STATUS_IS_WD_DIRTY(S) \ + (((S) & (GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED | \ + GIT_SUBMODULE_STATUS_WD_WD_MODIFIED | \ + GIT_SUBMODULE_STATUS_WD_UNTRACKED)) != 0) /** - * Iterate over all submodules of a repository. + * Lookup submodule information by name or path. + * + * Given either the submodule name or path (they are usually the same), this + * returns a structure describing the submodule. + * + * There are two expected error scenarios: + * + * - 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 + * 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. + * + * @param submodule Pointer to submodule description object pointer.. + * @param repo The repository. + * @param name The name of the submodule. Trailing slashes will be ignored. + * @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_EXTERN(int) git_submodule_lookup( + git_submodule **submodule, + git_repository *repo, + const char *name); + +/** + * Iterate over all tracked submodules of a repository. + * + * See the note on `git_submodule` above. This iterates over the tracked + * submodules as decribed therein. + * + * If you are concerned about items in the working directory that look like + * submodules but are not tracked, the diff API will generate a diff record + * for workdir items that look like submodules but are not tracked, showing + * them as added in the workdir. Also, the status API will treat the entire + * subdirectory of a contained git repo as a single GIT_STATUS_WT_NEW item. * * @param repo The repository * @param callback Function to be called with the name of each submodule. @@ -77,26 +183,326 @@ typedef struct { */ GIT_EXTERN(int) git_submodule_foreach( git_repository *repo, - int (*callback)(const char *name, void *payload), + int (*callback)(git_submodule *sm, const char *name, void *payload), void *payload); /** - * Lookup submodule information by name or path. + * Set up a new git submodule for checkout. * - * Given either the submodule name or path (they are ususally the same), - * this returns a structure describing the submodule. If the submodule - * does not exist, this will return GIT_ENOTFOUND and set the submodule - * pointer to NULL. + * This does "git submodule add" up to the fetch and checkout of the + * submodule contents. It preps a new submodule, creates an entry in + * .gitmodules and creates an empty initialized repository either at the + * given path in the working directory or in .git/modules with a gitlink + * from the working directory to the new repo. * - * @param submodule Pointer to submodule description object pointer.. - * @param repo The repository. - * @param name The name of the submodule. Trailing slashes will be ignored. - * @return 0 on success, GIT_ENOTFOUND if submodule does not exist, -1 on error + * To fully emulate "git submodule add" call this function, then open the + * submodule repo and perform the clone step as needed. Lastly, call + * `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 + * @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. + * @return 0 on success, GIT_EEXISTS if submodule already exists, + * -1 on other errors. */ -GIT_EXTERN(int) git_submodule_lookup( +GIT_EXTERN(int) git_submodule_add_setup( git_submodule **submodule, git_repository *repo, - const char *name); + const char *url, + const char *path, + int use_gitlink); + +/** + * Resolve the setup of a new git submodule. + * + * This should be called on a submodule once you have called add setup + * and done the clone of the submodule. This adds the .gitmodules file + * and the newly cloned submodule to the index to be ready to be committed + * (but doesn't actually do the commit). + * + * @param submodule The submodule to finish adding. + */ +GIT_EXTERN(int) git_submodule_add_finalize(git_submodule *submodule); + +/** + * Add current submodule HEAD commit to index of superproject. + * + * @param submodule The submodule to add to the index + * @param write_index Boolean if this should immediately write the index + * file. If you pass this as false, you will have to get the + * git_index and explicitly call `git_index_write()` on it to + * save the change. + * @return 0 on success, <0 on failure + */ +GIT_EXTERN(int) git_submodule_add_to_index( + git_submodule *submodule, + int write_index); + +/** + * Write submodule settings to .gitmodules file. + * + * This commits any in-memory changes to the submodule to the gitmodules + * file on disk. You may also be interested in `git_submodule_init()` which + * writes submodule info to ".git/config" (which is better for local changes + * to submodule settings) and/or `git_submodule_sync()` which writes + * settings about remotes to the actual submodule repository. + * + * @param submodule The submodule to write. + * @return 0 on success, <0 on failure. + */ +GIT_EXTERN(int) git_submodule_save(git_submodule *submodule); + +/** + * Get the containing repository for a submodule. + * + * This returns a pointer to the repository that contains the submodule. + * This is a just a reference to the repository that was passed to the + * original `git_submodule_lookup()` call, so if that repository has been + * freed, then this may be a dangling reference. + * + * @param submodule Pointer to submodule object + * @return Pointer to `git_repository` + */ +GIT_EXTERN(git_repository *) git_submodule_owner(git_submodule *submodule); + +/** + * Get the name of submodule. + * + * @param submodule Pointer to submodule object + * @return Pointer to the submodule name + */ +GIT_EXTERN(const char *) git_submodule_name(git_submodule *submodule); + +/** + * Get the path to the submodule. + * + * The path is almost always the same as the submodule name, but the + * two are actually not required to match. + * + * @param submodule Pointer to submodule object + * @return Pointer to the submodule path + */ +GIT_EXTERN(const char *) git_submodule_path(git_submodule *submodule); + +/** + * Get the URL for the submodule. + * + * @param submodule Pointer to submodule object + * @return Pointer to the submodule url + */ +GIT_EXTERN(const char *) git_submodule_url(git_submodule *submodule); + +/** + * Set the URL for the submodule. + * + * This sets the URL in memory for the submodule. This will be used for + * any following submodule actions while this submodule data is in memory. + * + * After calling this, you may wish to call `git_submodule_save()` to write + * the changes back to the ".gitmodules" file and `git_submodule_sync()` to + * write the changes to the checked out submodule repository. + * + * @param submodule Pointer to the submodule object + * @param url URL that should be used for the submodule + * @return 0 on success, <0 on failure + */ +GIT_EXTERN(int) git_submodule_set_url(git_submodule *submodule, const char *url); + +/** + * Get the OID for the submodule in the index. + * + * @param submodule Pointer to submodule object + * @return Pointer to git_oid or NULL if submodule is not in index. + */ +GIT_EXTERN(const git_oid *) git_submodule_index_oid(git_submodule *submodule); + +/** + * Get the OID for the submodule in the current HEAD tree. + * + * @param submodule Pointer to submodule object + * @return Pointer to git_oid or NULL if submodule is not in the HEAD. + */ +GIT_EXTERN(const git_oid *) git_submodule_head_oid(git_submodule *submodule); + +/** + * Get the OID for the submodule in the current working directory. + * + * This returns the OID that corresponds to looking up 'HEAD' in the checked + * out submodule. If there are pending changes in the index or anything + * else, this won't notice that. You should call `git_submodule_status()` + * for a more complete picture about the state of the working directory. + * + * @param submodule Pointer to submodule object + * @return Pointer to git_oid or NULL if submodule is not checked out. + */ +GIT_EXTERN(const git_oid *) git_submodule_wd_oid(git_submodule *submodule); + +/** + * Get the ignore rule for the submodule. + * + * There are four ignore values: + * + * - **GIT_SUBMODULE_IGNORE_NONE** will consider any change to the contents + * of the submodule from a clean checkout to be dirty, including the + * addition of untracked files. This is the default if unspecified. + * - **GIT_SUBMODULE_IGNORE_UNTRACKED** examines the contents of the + * working tree (i.e. call `git_status_foreach()` on the submodule) but + * UNTRACKED files will not count as making the submodule dirty. + * - **GIT_SUBMODULE_IGNORE_DIRTY** means to only check if the HEAD of the + * submodule has moved for status. This is fast since it does not need to + * scan the working tree of the submodule at all. + * - **GIT_SUBMODULE_IGNORE_ALL** means not to open the submodule repo. + * The working directory will be consider clean so long as there is a + * checked out version present. + */ +GIT_EXTERN(git_submodule_ignore_t) git_submodule_ignore( + git_submodule *submodule); + +/** + * Set the ignore rule for the submodule. + * + * This sets the ignore rule in memory for the submodule. This will be used + * for any following actions (such as `git_submodule_status()`) while the + * submodule is in memory. You should call `git_submodule_save()` if you + * want to persist the new ignore role. + * + * Calling this again with GIT_SUBMODULE_IGNORE_DEFAULT or calling + * `git_submodule_reload()` will revert the rule to the value that was in the + * original config. + * + * @return old value for ignore + */ +GIT_EXTERN(git_submodule_ignore_t) git_submodule_set_ignore( + git_submodule *submodule, + git_submodule_ignore_t ignore); + +/** + * Get the update rule for the submodule. + */ +GIT_EXTERN(git_submodule_update_t) git_submodule_update( + git_submodule *submodule); + +/** + * Set the update rule for the submodule. + * + * This sets the update rule in memory for the submodule. You should call + * `git_submodule_save()` if you want to persist the new update rule. + * + * Calling this again with GIT_SUBMODULE_UPDATE_DEFAULT or calling + * `git_submodule_reload()` will revert the rule to the value that was in the + * original config. + * + * @return old value for update + */ +GIT_EXTERN(git_submodule_update_t) git_submodule_set_update( + git_submodule *submodule, + git_submodule_update_t update); + +/** + * Read the fetchRecurseSubmodules rule for a submodule. + * + * This accesses the submodule..fetchRecurseSubmodules value for + * the submodule that controls fetching behavior for the submodule. + * + * Note that at this time, libgit2 does not honor this setting and the + * fetch functionality current ignores submodules. + * + * @return 0 if fetchRecurseSubmodules is false, 1 if true + */ +GIT_EXTERN(int) git_submodule_fetch_recurse_submodules( + git_submodule *submodule); + +/** + * Set the fetchRecurseSubmodules rule for a submodule. + * + * This sets the submodule..fetchRecurseSubmodules value for + * the submodule. You should call `git_submodule_save()` if you want + * to persist the new value. + * + * @param submodule The submodule to modify + * @param fetch_recurse_submodules Boolean value + * @return old value for fetchRecurseSubmodules + */ +GIT_EXTERN(int) git_submodule_set_fetch_recurse_submodules( + git_submodule *submodule, + int fetch_recurse_submodules); + +/** + * Copy submodule info into ".git/config" file. + * + * Just like "git submodule init", this copies information about the + * submodule into ".git/config". You can use the accessor functions + * above to alter the in-memory git_submodule object and control what + * is written to the config, overriding what is in .gitmodules. + * + * @param submodule The submodule to write into the superproject config + * @param overwrite By default, existing entries will not be overwritten, + * but setting this to true forces them to be updated. + * @return 0 on success, <0 on failure. + */ +GIT_EXTERN(int) git_submodule_init(git_submodule *submodule, int overwrite); + +/** + * Copy submodule remote info into submodule repo. + * + * This copies the information about the submodules URL into the checked out + * submodule config, acting like "git submodule sync". This is useful if + * you have altered the URL for the submodule (or it has been altered by a + * fetch of upstream changes) and you need to update your local repo. + */ +GIT_EXTERN(int) git_submodule_sync(git_submodule *submodule); + +/** + * Open the repository for a submodule. + * + * This is a newly opened repository object. The caller is responsible for + * calling `git_repository_free()` on it when done. Multiple calls to this + * function will return distinct `git_repository` objects. This will only + * work if the submodule is checked out into the working directory. + * + * @param subrepo Pointer to the submodule repo which was opened + * @param submodule Submodule to be opened + * @return 0 on success, <0 if submodule repo could not be opened. + */ +GIT_EXTERN(int) git_submodule_open( + git_repository **repo, + git_submodule *submodule); + +/** + * Reread submodule info from config, index, and HEAD. + * + * Call this to reread cached submodule information for this submodule if + * you have reason to believe that it has changed. + */ +GIT_EXTERN(int) git_submodule_reload(git_submodule *submodule); + +/** + * Reread all submodule info. + * + * Call this to reload all cached submodule information for the repo. + */ +GIT_EXTERN(int) git_submodule_reload_all(git_repository *repo); + +/** + * Get the status for a submodule. + * + * This looks at a submodule and tries to determine the status. It + * will return a combination of the `GIT_SUBMODULE_STATUS` values above. + * How deeply it examines the working directory to do this will depend + * on the `git_submodule_ignore_t` value for the submodule - which can be + * set either temporarily or permanently with `git_submodule_set_ignore()`. + * + * @param status Combination of `GIT_SUBMODULE_STATUS` flags + * @param submodule Submodule for which to get status + * @return 0 on success, <0 on error + */ +GIT_EXTERN(int) git_submodule_status( + unsigned int *status, + git_submodule *submodule); /** @} */ GIT_END_DECL diff --git a/git2/include/git2/tag.h b/git2/include/git2/tag.h index 859c28995..5602914f7 100644 --- a/git2/include/git2/tag.h +++ b/git2/include/git2/tag.h @@ -11,6 +11,7 @@ #include "types.h" #include "oid.h" #include "object.h" +#include "strarray.h" /** * @file git2/tag.h @@ -46,7 +47,7 @@ GIT_INLINE(int) git_tag_lookup(git_tag **tag, git_repository *repo, const git_oi * @param len the length of the short identifier * @return 0 or an error code */ -GIT_INLINE(int) git_tag_lookup_prefix(git_tag **tag, git_repository *repo, const git_oid *id, unsigned int len) +GIT_INLINE(int) git_tag_lookup_prefix(git_tag **tag, git_repository *repo, const git_oid *id, size_t len) { return git_object_lookup_prefix((git_object **)tag, repo, id, len, (git_otype)GIT_OBJ_TAG); } @@ -137,8 +138,8 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *tag); * this tag object. If `force` is true and a reference * already exists with the given name, it'll be replaced. * - * The message will be cleaned up from excess whitespace - * it will be made sure that the last line ends with a '\n'. + * The message will not be cleaned up. This can be achieved + * through `git_message_prettify()`. * * @param oid Pointer where to store the OID of the * newly created tag. If the tag already exists, this parameter @@ -181,7 +182,7 @@ GIT_EXTERN(int) git_tag_create( * @param repo Repository where to store the tag * @param buffer Raw tag data * @param force Overwrite existing tags - * @return 0 on sucess; error code otherwise + * @return 0 on success; error code otherwise */ GIT_EXTERN(int) git_tag_create_frombuffer( git_oid *oid, @@ -277,6 +278,21 @@ GIT_EXTERN(int) git_tag_list_match( const char *pattern, git_repository *repo); + +typedef int (*git_tag_foreach_cb)(const char *name, git_oid *oid, void *data); +/** + * Call callback `cb' for each tag in the repository + * + * @param repo Repository + * @param cb Callback function + * @param cb_data Pointer to callback data (optional) + */ +GIT_EXTERN(int) git_tag_foreach( + git_repository *repo, + git_tag_foreach_cb cb, + void *cb_data); + + /** * Recursively peel a tag until a non tag git_object * is met diff --git a/git2/include/git2/tree.h b/git2/include/git2/tree.h index 777f8ff0d..2ee1f4afa 100644 --- a/git2/include/git2/tree.h +++ b/git2/include/git2/tree.h @@ -46,7 +46,11 @@ GIT_INLINE(int) git_tree_lookup(git_tree **tree, git_repository *repo, const git * @param len the length of the short identifier * @return 0 or an error code */ -GIT_INLINE(int) git_tree_lookup_prefix(git_tree **tree, git_repository *repo, const git_oid *id, unsigned int len) +GIT_INLINE(int) git_tree_lookup_prefix( + git_tree **tree, + git_repository *repo, + const git_oid *id, + size_t len) { return git_object_lookup_prefix((git_object **)tree, repo, id, len, GIT_OBJ_TREE); } @@ -62,12 +66,33 @@ GIT_INLINE(int) git_tree_lookup_prefix(git_tree **tree, git_repository *repo, co * * @param tree the tree to close */ - GIT_INLINE(void) git_tree_free(git_tree *tree) { git_object_free((git_object *) tree); } +/** + * Free a tree entry + * + * IMPORTANT: This function is only needed for tree + * entries owned by the user, such as the ones returned + * by `git_tree_entry_dup`. + * + * @param entry The entry to free + */ +GIT_EXTERN(void) git_tree_entry_free(git_tree_entry *entry); + +/** + * Duplicate a tree entry + * + * Create a copy of a tree entry. The returned copy is owned + * by the user, and must be freed manually with + * `git_tree_entry_free`. + * + * @param entry A tree entry to duplicate + * @return a copy of the original entry + */ +GIT_EXTERN(git_tree_entry *) git_tree_entry_dup(const git_tree_entry *entry); /** * Get the id of a tree. @@ -75,7 +100,7 @@ GIT_INLINE(void) git_tree_free(git_tree *tree) * @param tree a previously loaded tree. * @return object identity for the tree. */ -GIT_EXTERN(const git_oid *) git_tree_id(git_tree *tree); +GIT_EXTERN(const git_oid *) git_tree_id(const git_tree *tree); /** * Get the number of entries listed in a tree @@ -83,7 +108,7 @@ GIT_EXTERN(const git_oid *) git_tree_id(git_tree *tree); * @param tree a previously loaded tree. * @return the number of entries in the tree */ -GIT_EXTERN(unsigned int) git_tree_entrycount(git_tree *tree); +GIT_EXTERN(unsigned int) git_tree_entrycount(const git_tree *tree); /** * Lookup a tree entry by its filename @@ -101,15 +126,26 @@ GIT_EXTERN(const git_tree_entry *) git_tree_entry_byname(git_tree *tree, const c * @param idx the position in the entry list * @return the tree entry; NULL if not found */ -GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex(git_tree *tree, unsigned int idx); +GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex(git_tree *tree, size_t idx); + +/** + * Lookup a tree entry by SHA value. + * + * Warning: this must examine every entry in the tree, so it is not fast. + * + * @param tree a previously loaded tree. + * @param oid the sha being looked for + * @return the tree entry; NULL if not found + */ +GIT_EXTERN(const git_tree_entry *) git_tree_entry_byoid(git_tree *tree, const git_oid *oid); /** * Get the UNIX file attributes of a tree entry * * @param entry a tree entry - * @return attributes as an integer + * @return filemode as an integer */ -GIT_EXTERN(unsigned int) git_tree_entry_attributes(const git_tree_entry *entry); +GIT_EXTERN(git_filemode_t) git_tree_entry_filemode(const git_tree_entry *entry); /** * Get the filename of a tree entry @@ -143,7 +179,10 @@ GIT_EXTERN(git_otype) git_tree_entry_type(const git_tree_entry *entry); * @param entry a tree entry * @return 0 or an error code */ -GIT_EXTERN(int) git_tree_entry_to_object(git_object **object_out, git_repository *repo, const git_tree_entry *entry); +GIT_EXTERN(int) git_tree_entry_to_object( + git_object **object_out, + git_repository *repo, + const git_tree_entry *entry); /** * Write a tree to the ODB from the index file @@ -178,7 +217,7 @@ GIT_EXTERN(int) git_tree_create_fromindex(git_oid *oid, git_index *index); * * @param builder_p Pointer where to store the tree builder * @param source Source tree to initialize the builder (optional) - * @return 0 on sucess; error code otherwise + * @return 0 on success; error code otherwise */ GIT_EXTERN(int) git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source); @@ -224,14 +263,25 @@ GIT_EXTERN(const git_tree_entry *) git_treebuilder_get(git_treebuilder *bld, con * The optional pointer `entry_out` can be used to retrieve a * pointer to the newly created/updated entry. * + * No attempt is being made to ensure that the provided oid points + * to an existing git object in the object database, nor that the + * attributes make sense regarding the type of the pointed at object. + * * @param entry_out Pointer to store the entry (optional) * @param bld Tree builder * @param filename Filename of the entry * @param id SHA1 oid of the entry - * @param attributes Folder attributes of the entry + * @param filemode Folder attributes of the entry. This parameter must + * be valued with one of the following entries: 0040000, 0100644, + * 0100755, 0120000 or 0160000. * @return 0 or an error code */ -GIT_EXTERN(int) git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, const char *filename, const git_oid *id, unsigned int attributes); +GIT_EXTERN(int) git_treebuilder_insert( + const git_tree_entry **entry_out, + git_treebuilder *bld, + const char *filename, + const git_oid *id, + git_filemode_t filemode); /** * Remove an entry from the builder by its filename @@ -252,7 +302,10 @@ GIT_EXTERN(int) git_treebuilder_remove(git_treebuilder *bld, const char *filenam * @param bld Tree builder * @param filter Callback to filter entries */ -GIT_EXTERN(void) git_treebuilder_filter(git_treebuilder *bld, int (*filter)(const git_tree_entry *, void *), void *payload); +GIT_EXTERN(void) git_treebuilder_filter( + git_treebuilder *bld, + int (*filter)(const git_tree_entry *, void *), + void *payload); /** * Write the contents of the tree builder as a tree object @@ -269,21 +322,24 @@ GIT_EXTERN(void) git_treebuilder_filter(git_treebuilder *bld, int (*filter)(cons GIT_EXTERN(int) git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld); /** - * Retrieve a subtree contained in a tree, given its - * relative path. + * Retrieve a tree entry contained in a tree or in any + * of its subtrees, given its relative path. * - * The returned tree is owned by the repository and - * should be closed with the `git_object_free` method. + * The returned tree entry is owned by the user and must + * be freed manually with `git_tree_entry_free`. * - * @param subtree Pointer where to store the subtree + * @param entry Pointer where to store the tree entry * @param root A previously loaded tree which will be the root of the relative path - * @param subtree_path Path to the contained subtree - * @return 0 on success; GIT_ENOTFOUND if the path does not lead to a subtree + * @param subtree_path Path to the contained entry + * @return 0 on success; GIT_ENOTFOUND if the path does not exist */ -GIT_EXTERN(int) git_tree_get_subtree(git_tree **subtree, git_tree *root, const char *subtree_path); +GIT_EXTERN(int) git_tree_entry_bypath( + git_tree_entry **entry, + git_tree *root, + const char *path); /** Callback for the tree traversal method */ -typedef int (*git_treewalk_cb)(const char *root, git_tree_entry *entry, void *payload); +typedef int (*git_treewalk_cb)(const char *root, const git_tree_entry *entry, void *payload); /** Tree traversal modes */ enum git_treewalk_mode { @@ -301,8 +357,9 @@ enum git_treewalk_mode { * the current (relative) root for the entry and the entry * data itself. * - * If the callback returns a negative value, the passed entry - * will be skiped on the traversal. + * If the callback returns a positive value, the passed entry will be + * skipped on the traversal (in pre mode). A negative value stops the + * walk. * * @param tree The tree to walk * @param callback Function to call on each tree entry diff --git a/git2/include/git2/types.h b/git2/include/git2/types.h index cfb0acf33..01ddbf3d6 100644 --- a/git2/include/git2/types.h +++ b/git2/include/git2/types.h @@ -32,6 +32,9 @@ GIT_BEGIN_DECL * stat() functions, for all platforms. */ #include +#ifdef __amigaos4__ +#include +#endif #if defined(_MSC_VER) @@ -134,6 +137,9 @@ typedef struct git_reflog git_reflog; /** Representation of a git note */ typedef struct git_note git_note; +/** Representation of a git packbuilder */ +typedef struct git_packbuilder git_packbuilder; + /** Time in a signature */ typedef struct git_time { git_time_t time; /** time in seconds from epoch */ @@ -166,10 +172,28 @@ typedef enum { GIT_BRANCH_REMOTE = 2, } git_branch_t; +/** Kinds of reset operation. */ +typedef enum { + GIT_RESET_SOFT = 1, + GIT_RESET_MIXED = 2, + GIT_RESET_HARD = 3, +} git_reset_type; + +/** Valid modes for index and tree entries. */ +typedef enum { + GIT_FILEMODE_NEW = 0000000, + GIT_FILEMODE_TREE = 0040000, + GIT_FILEMODE_BLOB = 0100644, + GIT_FILEMODE_BLOB_EXECUTABLE = 0100755, + GIT_FILEMODE_LINK = 0120000, + GIT_FILEMODE_COMMIT = 0160000, +} git_filemode_t; + typedef struct git_refspec git_refspec; typedef struct git_remote git_remote; typedef struct git_remote_head git_remote_head; +typedef struct git_remote_callbacks git_remote_callbacks; /** @} */ GIT_END_DECL diff --git a/git2/include/git2/windows.h b/git2/include/git2/windows.h deleted file mode 100644 index 8b743f0aa..000000000 --- a/git2/include/git2/windows.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2009-2012 the libgit2 contributors - * - * 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_windows_h__ -#define INCLUDE_git_windows_h__ - -#include "common.h" - -/** - * @file git2/windows.h - * @brief Windows-specific functions - * @ingroup Git - * @{ - */ -GIT_BEGIN_DECL - -/** - * Set the active codepage for Windows syscalls - * - * All syscalls performed by the library will assume - * this codepage when converting paths and strings - * to use by the Windows kernel. - * - * The default value of UTF-8 will work automatically - * with most Git repositories created on Unix systems. - * - * This settings needs only be changed when working - * with repositories that contain paths in specific, - * non-UTF codepages. - * - * A full list of all available codepage identifiers may - * be found at: - * - * http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx - * - * @param codepage numeric codepage identifier - */ -GIT_EXTERN(void) gitwin_set_codepage(unsigned int codepage); - -/** - * Return the active codepage for Windows syscalls - * - * @return numeric codepage identifier - */ -GIT_EXTERN(unsigned int) gitwin_get_codepage(void); - -/** - * Set the active Windows codepage to UTF-8 (this is - * the default value) - */ -GIT_EXTERN(void) gitwin_set_utf8(void); - -/** @} */ -GIT_END_DECL -#endif - diff --git a/git2/libgit2.gypi b/git2/libgit2.gypi index 364e7840a..028551a47 100644 --- a/git2/libgit2.gypi +++ b/git2/libgit2.gypi @@ -33,7 +33,14 @@ 'git2/include/git2/tree.h', 'git2/include/git2/types.h', 'git2/include/git2/version.h', - 'git2/include/git2/windows.h', + 'git2/include/git2/checkout.h', + 'git2/include/git2/clone.h', + 'git2/include/git2/ignore.h', + 'git2/include/git2/message.h', + 'git2/include/git2/pack.h', + 'git2/include/git2/reset.h', + 'git2/include/git2/revparse.h', + 'git2/include/git2/strarray.h', ], } -} \ No newline at end of file +}