summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml5
-rw-r--r--CONVENTIONS.md3
-rw-r--r--examples/diff.c2
-rw-r--r--examples/network/clone.c2
-rw-r--r--examples/network/fetch.c3
-rw-r--r--include/git2/branch.h15
-rw-r--r--include/git2/checkout.h3
-rw-r--r--include/git2/config.h3
-rw-r--r--include/git2/diff.h93
-rw-r--r--include/git2/errors.h1
-rw-r--r--include/git2/object.h5
-rw-r--r--include/git2/odb_backend.h4
-rw-r--r--include/git2/reflog.h5
-rw-r--r--include/git2/refs.h41
-rw-r--r--include/git2/remote.h29
-rw-r--r--include/git2/repository.h4
-rw-r--r--include/git2/revparse.h3
-rw-r--r--include/git2/status.h3
-rw-r--r--include/git2/strarray.h5
-rw-r--r--include/git2/tag.h16
-rw-r--r--include/git2/transport.h5
-rw-r--r--src/checkout.c16
-rw-r--r--src/common.h33
-rw-r--r--src/config.c2
-rw-r--r--src/config_cache.c2
-rw-r--r--src/config_file.c4
-rw-r--r--src/delta-apply.c13
-rw-r--r--src/delta-apply.h17
-rw-r--r--src/diff.c8
-rw-r--r--src/diff.h1
-rw-r--r--src/diff_output.c2
-rw-r--r--src/diff_tform.c5
-rw-r--r--src/errors.c9
-rw-r--r--src/iterator.c40
-rw-r--r--src/notes.c1
-rw-r--r--src/object.c44
-rw-r--r--src/odb.c2
-rw-r--r--src/odb_loose.c1
-rw-r--r--src/odb_pack.c21
-rw-r--r--src/pack.c50
-rw-r--r--src/pack.h6
-rw-r--r--src/reflog.c15
-rw-r--r--src/refs.c39
-rw-r--r--src/remote.c75
-rw-r--r--src/repository.c5
-rw-r--r--src/reset.c3
-rw-r--r--src/revparse.c85
-rw-r--r--src/signature.c2
-rw-r--r--src/stash.c12
-rw-r--r--src/status.c14
-rw-r--r--src/submodule.c6
-rw-r--r--src/tag.c5
-rw-r--r--src/transports/local.c5
-rw-r--r--src/transports/smart.c1
-rw-r--r--src/tree.c45
-rw-r--r--tests-clar/checkout/index.c22
-rw-r--r--tests-clar/checkout/tree.c2
-rw-r--r--tests-clar/checkout/typechange.c2
-rw-r--r--tests-clar/commit/parse.c4
-rw-r--r--tests-clar/config/backend.c21
-rw-r--r--tests-clar/diff/blob.c24
-rw-r--r--tests-clar/diff/diff_helpers.h1
-rw-r--r--tests-clar/diff/diffiter.c30
-rw-r--r--tests-clar/diff/index.c25
-rw-r--r--tests-clar/diff/rename.c38
-rw-r--r--tests-clar/diff/tree.c34
-rw-r--r--tests-clar/diff/workdir.c38
-rw-r--r--tests-clar/network/fetch.c5
-rw-r--r--tests-clar/network/push_util.h3
-rw-r--r--tests-clar/network/remoterename.c4
-rw-r--r--tests-clar/network/remotes.c59
-rw-r--r--tests-clar/object/peel.c13
-rw-r--r--tests-clar/object/tag/write.c31
-rw-r--r--tests-clar/object/tree/attributes.c39
-rw-r--r--tests-clar/odb/sorting.c4
-rw-r--r--tests-clar/refs/branches/create.c9
-rw-r--r--tests-clar/refs/branches/lookup.c8
-rw-r--r--tests-clar/refs/branches/move.c5
-rw-r--r--tests-clar/refs/branches/tracking.c11
-rw-r--r--tests-clar/refs/create.c29
-rw-r--r--tests-clar/refs/normalize.c4
-rw-r--r--tests-clar/refs/peel.c2
-rw-r--r--tests-clar/refs/read.c28
-rw-r--r--tests-clar/refs/reflog/reflog.c12
-rw-r--r--tests-clar/refs/rename.c12
-rw-r--r--tests-clar/refs/revparse.c91
-rw-r--r--tests-clar/refs/update.c29
-rw-r--r--tests-clar/repo/init.c9
-rw-r--r--tests-clar/resources/deprecated-mode.git/objects/08/10fb7818088ff5ac41ee49199b51473b1bd6c7bin0 -> 350 bytes
-rw-r--r--tests-clar/status/ignore.c8
-rw-r--r--tests-clar/status/worktree.c88
91 files changed, 1188 insertions, 395 deletions
diff --git a/.travis.yml b/.travis.yml
index 256227589..f1660b25e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -46,3 +46,8 @@ notifications:
- irc.freenode.net#libgit2
on_success: change
on_failure: always
+ campfire:
+ on_success: always
+ on_failure: always
+ rooms:
+ - secure: "sH0dpPWMirbEe7AvLddZ2yOp8rzHalGmv0bYL/LIhVw3JDI589HCYckeLMSB\n3e/FeXw4bn0EqXWEXijVa4ijbilVY6d8oprdqMdWHEodng4KvY5vID3iZSGT\nxylhahO1XHmRynKQLOAvxlc93IlpVW38vQfby8giIY1nkpspb2w="
diff --git a/CONVENTIONS.md b/CONVENTIONS.md
index ea5e40ee6..10d9c8644 100644
--- a/CONVENTIONS.md
+++ b/CONVENTIONS.md
@@ -123,8 +123,7 @@ GIT_EXTERN(int) git_foo_id(
int b);
```
-Public headers are indented with spaces, three to a tab. Internal code is
-indented with tabs; set your editor's tab width to 3 for best effect.
+Indentation is done with tabs; set your editor's tab width to 3 for best effect.
## Documentation
diff --git a/examples/diff.c b/examples/diff.c
index a465182ba..b81a8682a 100644
--- a/examples/diff.c
+++ b/examples/diff.c
@@ -133,7 +133,7 @@ int main(int argc, char *argv[])
{
git_repository *repo = NULL;
git_tree *t1 = NULL, *t2 = NULL;
- git_diff_options opts;
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff;
int i, color = -1, compact = 0, cached = 0;
char *a, *dir = ".", *treeish1 = NULL, *treeish2 = NULL;
diff --git a/examples/network/clone.c b/examples/network/clone.c
index a718f3084..7596523c2 100644
--- a/examples/network/clone.c
+++ b/examples/network/clone.c
@@ -51,7 +51,7 @@ int do_clone(git_repository *repo, int argc, char **argv)
{
progress_data pd;
git_repository *cloned_repo = NULL;
- git_checkout_opts checkout_opts;
+ git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT;
const char *url = argv[1];
const char *path = argv[2];
int error;
diff --git a/examples/network/fetch.c b/examples/network/fetch.c
index e341d2d6c..8048fd67a 100644
--- a/examples/network/fetch.c
+++ b/examples/network/fetch.c
@@ -70,7 +70,7 @@ int fetch(git_repository *repo, int argc, char **argv)
const git_transfer_progress *stats;
pthread_t worker;
struct dl_data data;
- git_remote_callbacks callbacks;
+ git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
argc = argc;
// Figure out whether it's a named remote or a URL
@@ -81,7 +81,6 @@ int fetch(git_repository *repo, int argc, char **argv)
}
// Set up the callbacks (only update_tips for now)
- memset(&callbacks, 0, sizeof(callbacks));
callbacks.update_tips = &update_cb;
callbacks.progress = &progress_cb;
git_remote_set_callbacks(remote, &callbacks);
diff --git a/include/git2/branch.h b/include/git2/branch.h
index c9ae9cc5d..f55903cd6 100644
--- a/include/git2/branch.h
+++ b/include/git2/branch.h
@@ -29,6 +29,9 @@ GIT_BEGIN_DECL
*
* The returned reference must be freed by the user.
*
+ * The branch name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @param out Pointer where to store the underlying reference.
*
* @param branch_name Name for the branch; this name is
@@ -42,7 +45,7 @@ GIT_BEGIN_DECL
*
* @param force Overwrite existing branch.
*
- * @return 0 or an error code.
+ * @return 0, GIT_EINVALIDSPEC or an error code.
* A proper reference is written in the refs/heads namespace
* pointing to the provided target commit.
*/
@@ -94,6 +97,9 @@ GIT_EXTERN(int) git_branch_foreach(
/**
* Move/rename an existing local branch reference.
*
+ * The new branch name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @param branch Current underlying reference of the branch.
*
* @param new_branch_name Target name of the branch once the move
@@ -101,7 +107,7 @@ GIT_EXTERN(int) git_branch_foreach(
*
* @param force Overwrite existing branch.
*
- * @return 0 on success, or an error code.
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code.
*/
GIT_EXTERN(int) git_branch_move(
git_reference *branch,
@@ -113,6 +119,9 @@ GIT_EXTERN(int) git_branch_move(
*
* The generated reference must be freed by the user.
*
+ * The branch name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @param out pointer to the looked-up branch reference
*
* @param repo the repository to look up the branch
@@ -124,7 +133,7 @@ GIT_EXTERN(int) git_branch_move(
* 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.
+ * exists, GIT_EINVALIDSPEC, otherwise an error code.
*/
GIT_EXTERN(int) git_branch_lookup(
git_reference **out,
diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index bd988db2c..c36e2a41b 100644
--- a/include/git2/checkout.h
+++ b/include/git2/checkout.h
@@ -186,7 +186,8 @@ typedef struct git_checkout_opts {
git_strarray paths;
} git_checkout_opts;
-#define GIT_CHECKOUT_OPTS_INIT {1, 0}
+#define GIT_CHECKOUT_OPTS_VERSION 1
+#define GIT_CHECKOUT_OPTS_INIT {GIT_CHECKOUT_OPTS_VERSION}
/**
* Updates files in the index and the working tree to match the content of the
diff --git a/include/git2/config.h b/include/git2/config.h
index af4d54044..b186e70da 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -49,6 +49,7 @@ typedef int (*git_config_foreach_cb)(const git_config_entry *, void *);
* access a configuration file
*/
struct git_config_backend {
+ unsigned int version;
struct git_config *cfg;
/* Open means open the file/database and parse if necessary */
@@ -62,6 +63,8 @@ struct git_config_backend {
int (*refresh)(struct git_config_backend *);
void (*free)(struct git_config_backend *);
};
+#define GIT_CONFIG_BACKEND_VERSION 1
+#define GIT_CONFIG_BACKEND_INIT {GIT_CONFIG_BACKEND_VERSION}
typedef enum {
GIT_CVAR_FALSE = 0,
diff --git a/include/git2/diff.h b/include/git2/diff.h
index fd00378af..49f781ddd 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -17,6 +17,9 @@
* @file git2/diff.h
* @brief Git tree and file differencing routines.
*
+ * Overview
+ * --------
+ *
* Calculating diffs is generally done in two phases: building a diff list
* then traversing the diff list. This makes is easier to share logic
* across the various types of diffs (tree vs tree, workdir vs index, etc.),
@@ -24,6 +27,35 @@
* such as rename detected, in between the steps. When you are done with a
* diff list object, it must be freed.
*
+ * Terminology
+ * -----------
+ *
+ * To understand the diff APIs, you should know the following terms:
+ *
+ * - A `diff` or `diff list` represents the cumulative list of differences
+ * between two snapshots of a repository (possibly filtered by a set of
+ * file name patterns). This is the `git_diff_list` object.
+ * - A `delta` is a file pair with an old and new revision. The old version
+ * may be absent if the file was just created and the new version may be
+ * absent if the file was deleted. A diff is mostly just a list of deltas.
+ * - A `binary` file / delta is a file (or pair) for which no text diffs
+ * should be generated. A diff list can contain delta entries that are
+ * binary, but no diff content will be output for those files. There is
+ * a base heuristic for binary detection and you can further tune the
+ * behavior with git attributes or diff flags and option settings.
+ * - A `hunk` is a span of modified lines in a delta along with some stable
+ * surrounding context. You can configure the amount of context and other
+ * properties of how hunks are generated. Each hunk also comes with a
+ * header that described where it starts and ends in both the old and new
+ * versions in the delta.
+ * - A `line` is a range of characters inside a hunk. It could be a context
+ * line (i.e. in both old and new versions), an added line (i.e. only in
+ * the new version), or a removed line (i.e. only in the old version).
+ * Unfortunately, we don't know anything about the encoding of data in the
+ * file being diffed, so we cannot tell you much about the line content.
+ * Line data will not be NUL-byte terminated, however, because it will be
+ * just a span of bytes inside the larger file.
+ *
* @ingroup Git
* @{
*/
@@ -97,25 +129,32 @@ typedef enum {
* values. Similarly, passing NULL for the options structure will
* give the defaults. The default values are marked below.
*
- * - flags: a combination of the git_diff_option_t 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
+ * - `flags` is a combination of the `git_diff_option_t` values above
+ * - `context_lines` is the number of unchanged lines that define the
+ * boundary of a hunk (and to display before and after)
+ * - `interhunk_lines` is the maximum number of unchanged lines between
+ * hunk boundaries before the hunks will be merged into a one.
+ * - `old_prefix` is the virtual "directory" to prefix to old file names
+ * in hunk headers (default "a")
+ * - `new_prefix` is the virtual "directory" to prefix to new file names
+ * in hunk headers (default "b")
+ * - `pathspec` is an array of paths / fnmatch patterns to constrain diff
+ * - `max_size` is a file size above which a blob will be marked as binary
*/
typedef struct {
- unsigned int version; /**< version for the struct */
- uint32_t flags; /**< defaults to GIT_DIFF_NORMAL */
- uint16_t context_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 */
+ unsigned int version; /**< version for the struct */
+ uint32_t flags; /**< defaults to GIT_DIFF_NORMAL */
+ uint16_t context_lines; /**< defaults to 3 */
+ uint16_t interhunk_lines; /**< defaults to 0 */
+ const char *old_prefix; /**< defaults to "a" */
+ const 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;
+#define GIT_DIFF_OPTIONS_VERSION 1
+#define GIT_DIFF_OPTIONS_INIT {GIT_DIFF_OPTIONS_VERSION}
+
/**
* The diff list object that contains all individual file deltas.
*/
@@ -139,6 +178,13 @@ typedef enum {
/**
* What type of change is described by a git_diff_delta?
+ *
+ * `GIT_DELTA_RENAMED` and `GIT_DELTA_COPIED` will only show up if you run
+ * `git_diff_find_similar()` on the diff list object.
+ *
+ * `GIT_DELTA_TYPECHANGE` only shows up given `GIT_DIFF_INCLUDE_TYPECHANGE`
+ * in the option flags (otherwise type changes will be split into ADDED /
+ * DELETED pairs).
*/
typedef enum {
GIT_DELTA_UNMODIFIED = 0,
@@ -154,6 +200,21 @@ typedef enum {
/**
* Description of one side of a diff.
+ *
+ * The `oid` is the `git_oid` of the item. If it represents an absent side
+ * of a diff (e.g. the `old_file` of a `GIT_DELTA_ADDED` delta), then the
+ * oid will be zeroes.
+ *
+ * `path` is the NUL-terminated path to the file relative to the working
+ * directory of the repository.
+ *
+ * `size` is the size of the file in bytes.
+ *
+ * `flags` is a combination of the `git_diff_file_flag_t` types, but those
+ * are largely internal values.
+ *
+ * `mode` is, roughly, the stat() st_mode value for the item. This will be
+ * restricted to one of the `git_filemode_t` values.
*/
typedef struct {
git_oid oid;
@@ -304,6 +365,8 @@ typedef struct {
unsigned int target_limit;
} git_diff_find_options;
+#define GIT_DIFF_FIND_OPTIONS_VERSION 1
+#define GIT_DIFF_FIND_OPTIONS_INIT {GIT_DIFF_FIND_OPTIONS_VERSION}
/** @name Diff List Generator Functions
*
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 9dd42f0c4..63b6bc8ee 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -30,6 +30,7 @@ enum {
GIT_EORPHANEDHEAD = -9,
GIT_EUNMERGED = -10,
GIT_ENONFASTFORWARD = -11,
+ GIT_EINVALIDSPEC = -12,
GIT_PASSTHROUGH = -30,
GIT_ITEROVER = -31,
diff --git a/include/git2/object.h b/include/git2/object.h
index fcc56cb27..e5ca17e16 100644
--- a/include/git2/object.h
+++ b/include/git2/object.h
@@ -179,8 +179,9 @@ GIT_EXTERN(size_t) git_object__size(git_otype type);
*
* @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
+ * @param target_type The type of the requested object (GIT_OBJ_COMMIT,
+ * GIT_OBJ_TAG, GIT_OBJ_TREE, GIT_OBJ_BLOB or GIT_OBJ_ANY).
+ * @return 0 on success, GIT_EAMBIGUOUS, GIT_ENOTFOUND or an error code
*/
GIT_EXTERN(int) git_object_peel(
git_object **peeled,
diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h
index 04658f9b3..19a154022 100644
--- a/include/git2/odb_backend.h
+++ b/include/git2/odb_backend.h
@@ -33,6 +33,7 @@ typedef int (*git_odb_foreach_cb)(const git_oid *id, void *payload);
* An instance for a custom backend
*/
struct git_odb_backend {
+ unsigned int version;
git_odb *odb;
/* read and read_prefix each return to libgit2 a buffer which
@@ -98,6 +99,9 @@ struct git_odb_backend {
void (* free)(struct git_odb_backend *);
};
+#define GIT_ODB_BACKEND_VERSION 1
+#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION}
+
/** Streaming mode */
enum {
GIT_STREAM_RDONLY = (1 << 1),
diff --git a/include/git2/reflog.h b/include/git2/reflog.h
index 45dff2165..418826d1d 100644
--- a/include/git2/reflog.h
+++ b/include/git2/reflog.h
@@ -63,9 +63,12 @@ GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *id, const g
*
* The reflog to be renamed is expected to already exist
*
+ * The new name will be checked for validity.
+ * See `git_reference_create_symbolic()` for rules about valid names.
+ *
* @param ref the reference
* @param name the new name of the reference
- * @return 0 or an error code
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_reflog_rename(git_reference *ref, const char *name);
diff --git a/include/git2/refs.h b/include/git2/refs.h
index c92646115..cfc96a68c 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -26,13 +26,13 @@ GIT_BEGIN_DECL
*
* The returned reference must be freed by the user.
*
- * See `git_reference_create_symbolic()` for documentation about valid
- * reference names.
+ * The name will be checked for validity.
+ * See `git_reference_create_symbolic()` for rules about valid names.
*
* @param out pointer to the looked-up reference
* @param repo the repository to look up the reference
* @param name the long name for the reference (e.g. HEAD, refs/heads/master, refs/tags/v0.1.0, ...)
- * @return 0 or an error code (ENOTFOUND, EINVALIDSPEC)
+ * @return 0 on success, ENOTFOUND, EINVALIDSPEC or an error code.
*/
GIT_EXTERN(int) git_reference_lookup(git_reference **out, git_repository *repo, const char *name);
@@ -43,11 +43,13 @@ GIT_EXTERN(int) git_reference_lookup(git_reference **out, git_repository *repo,
* through to the object id that it refers to. This avoids having to
* allocate or free any `git_reference` objects for simple situations.
*
+ * The name will be checked for validity.
+ * See `git_reference_create_symbolic()` for rules about valid names.
+ *
* @param out Pointer to oid to be filled in
* @param repo The repository in which to look up the reference
* @param name The long name for the reference
- * @return 0 on success, -1 if name could not be resolved (EINVALIDSPEC,
- * ENOTFOUND, etc)
+ * @return 0 on success, ENOTFOUND, EINVALIDSPEC or an error code.
*/
GIT_EXTERN(int) git_reference_name_to_id(
git_oid *out, git_repository *repo, const char *name);
@@ -79,7 +81,7 @@ GIT_EXTERN(int) git_reference_name_to_id(
* @param name The name of the reference
* @param target The target of the reference
* @param force Overwrite existing references
- * @return 0 or an error code (EEXISTS, EINVALIDSPEC)
+ * @return 0 on success, EEXISTS, EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repository *repo, const char *name, const char *target, int force);
@@ -111,7 +113,7 @@ GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repositor
* @param name The name of the reference
* @param id The object id pointed to by the reference.
* @param force Overwrite existing references
- * @return 0 or an error code (EINVALIDSPEC, EEXISTS)
+ * @return 0 on success, EEXISTS, EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force);
@@ -193,9 +195,12 @@ GIT_EXTERN(git_repository *) git_reference_owner(const git_reference *ref);
*
* The reference will be automatically updated in memory and on disk.
*
+ * The target name will be checked for validity.
+ * See `git_reference_create_symbolic()` for rules about valid names.
+ *
* @param ref The reference
* @param target The new target for the reference
- * @return 0 or an error code (EINVALIDSPEC)
+ * @return 0 on success, EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_reference_symbolic_set_target(git_reference *ref, const char *target);
@@ -216,8 +221,9 @@ GIT_EXTERN(int) git_reference_set_target(git_reference *ref, const git_oid *id);
* Rename an existing reference.
*
* This method works for both direct and symbolic references.
- * The new name will be checked for validity and may be
- * modified into a normalized form.
+ *
+ * The new name will be checked for validity.
+ * See `git_reference_create_symbolic()` for rules about valid names.
*
* The given git_reference will be updated in place.
*
@@ -234,7 +240,7 @@ GIT_EXTERN(int) git_reference_set_target(git_reference *ref, const git_oid *id);
* @param ref The reference to rename
* @param name The new name for the reference
* @param force Overwrite an existing reference
- * @return 0 or an error code (EINVALIDSPEC, EEXISTS)
+ * @return 0 on success, EINVALIDSPEC, EEXISTS or an error code
*
*/
GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *name, int force);
@@ -381,7 +387,7 @@ 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),
+ git_reference_foreach_cb callback,
void *payload);
/**
@@ -446,13 +452,15 @@ typedef enum {
* Once normalized, if the reference name is valid, it will be returned in
* the user allocated buffer.
*
+ * See `git_reference_create_symbolic()` for rules about valid names.
+ *
* @param buffer_out User allocated buffer to store normalized name
* @param buffer_size Size of buffer_out
* @param name Reference name to be checked.
* @param flags Flags to constrain name validation rules - see the
* GIT_REF_FORMAT constants above.
- * @return 0 on success or error code (GIT_EBUFS if buffer is too small, -1
- * if reference is invalid)
+ * @return 0 on success, GIT_EBUFS if buffer is too small, EINVALIDSPEC
+ * or an error code.
*/
GIT_EXTERN(int) git_reference_normalize_name(
char *buffer_out,
@@ -471,8 +479,9 @@ GIT_EXTERN(int) git_reference_normalize_name(
*
* @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
+ * @param target_type The type of the requested object (GIT_OBJ_COMMIT,
+ * GIT_OBJ_TAG, GIT_OBJ_TREE, GIT_OBJ_BLOB or GIT_OBJ_ANY).
+ * @return 0 on success, GIT_EAMBIGUOUS, GIT_ENOTFOUND or an error code
*/
GIT_EXTERN(int) git_reference_peel(
git_object **out,
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 6c70d7fbc..af73ca8b3 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -39,30 +39,39 @@ typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, voi
* Create a remote with the default refspecs in memory. You can use
* this when you have a URL instead of a remote's name.
*
+ * The name, when provided, will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @param out pointer to the new remote object
* @param repo the associated repository
- * @param name the remote's name
+ * @param name the optional remote's name
* @param url the remote repository's URL
* @param fetch the fetch refspec to use for this remote
- * @return 0 or an error code
+ * @return 0, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_remote_new(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch);
/**
* Get the information for a particular remote
*
+ * The name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @param out pointer to the new remote object
* @param repo the associated repository
* @param name the remote's name
- * @return 0 or an error code
+ * @return 0, GIT_ENOTFOUND, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_remote_load(git_remote **out, git_repository *repo, const char *name);
/**
* Save a remote to its repository's configuration
*
+ * One can't save a nameless inmemory remote. Doing so will
+ * result in a GIT_EINVALIDSPEC being returned.
+ *
* @param remote the remote to save to config
- * @return 0 or an error code
+ * @return 0, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_remote_save(const git_remote *remote);
@@ -338,12 +347,16 @@ typedef enum git_remote_completion_type {
* Set the calbacks to be called by the remote.
*/
struct git_remote_callbacks {
+ unsigned int version;
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 *payload;
};
+#define GIT_REMOTE_CALLBACKS_VERSION 1
+#define GIT_REMOTE_CALLBACKS_INIT {GIT_REMOTE_CALLBACKS_VERSION}
+
/**
* Set the callbacks for a remote
*
@@ -352,8 +365,9 @@ struct git_remote_callbacks {
*
* @param remote the remote to configure
* @param callbacks a pointer to the user's callback settings
+ * @return 0 or an error code
*/
-GIT_EXTERN(void) git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks);
+GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks);
/**
* Get the statistics structure that is filled in by the fetch operation.
@@ -391,12 +405,15 @@ GIT_EXTERN(void) git_remote_set_autotag(
* All remote-tracking branches and configuration settings
* for the remote are updated.
*
+ * The new name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @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
+ * @return 0, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_remote_rename(
git_remote *remote,
diff --git a/include/git2/repository.h b/include/git2/repository.h
index e91108a33..216f59b51 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -239,6 +239,7 @@ typedef enum {
* will be added pointing to this URL.
*/
typedef struct {
+ unsigned int version;
uint32_t flags;
uint32_t mode;
const char *workdir_path;
@@ -248,6 +249,9 @@ typedef struct {
const char *origin_url;
} git_repository_init_options;
+#define GIT_REPOSITORY_INIT_OPTIONS_VERSION 1
+#define GIT_REPOSITORY_INIT_OPTIONS_INIT {GIT_REPOSITORY_INIT_OPTIONS_VERSION}
+
/**
* Create a new Git repository in the given folder with extended controls.
*
diff --git a/include/git2/revparse.h b/include/git2/revparse.h
index 4567027e5..3df6fef7f 100644
--- a/include/git2/revparse.h
+++ b/include/git2/revparse.h
@@ -27,7 +27,8 @@ GIT_BEGIN_DECL
* @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)
+ * @return 0 on success, GIT_ENOTFOUND, GIT_EAMBIGUOUS,
+ * GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_revparse_single(git_object **out, git_repository *repo, const char *spec);
diff --git a/include/git2/status.h b/include/git2/status.h
index c6926f343..a898d1f34 100644
--- a/include/git2/status.h
+++ b/include/git2/status.h
@@ -164,6 +164,9 @@ typedef struct {
git_strarray pathspec;
} git_status_options;
+#define GIT_STATUS_OPTIONS_VERSION 1
+#define GIT_STATUS_OPTIONS_INIT {GIT_STATUS_OPTIONS_VERSION}
+
/**
* Gather file status information and run callbacks as requested.
*
diff --git a/include/git2/strarray.h b/include/git2/strarray.h
index 030567978..338d13873 100644
--- a/include/git2/strarray.h
+++ b/include/git2/strarray.h
@@ -19,11 +19,10 @@
GIT_BEGIN_DECL
/** Array of strings */
-typedef struct _git_strarray git_strarray;
-struct _git_strarray {
+typedef struct git_strarray {
char **strings;
size_t count;
-};
+} git_strarray;
/**
* Close a string array object
diff --git a/include/git2/tag.h b/include/git2/tag.h
index f82a6c9f9..a9773be56 100644
--- a/include/git2/tag.h
+++ b/include/git2/tag.h
@@ -144,6 +144,10 @@ GIT_EXTERN(const char *) git_tag_message(const git_tag *tag);
* The message will not be cleaned up. This can be achieved
* through `git_message_prettify()`.
*
+ * The tag name will be checked for validity. You must avoid
+ * the characters '~', '^', ':', '\\', '?', '[', and '*', and the
+ * sequences ".." and "@{" which have special meaning to revparse.
+ *
* @param oid Pointer where to store the OID of the
* newly created tag. If the tag already exists, this parameter
* will be the oid of the existing tag, and the function will
@@ -165,7 +169,7 @@ GIT_EXTERN(const char *) git_tag_message(const git_tag *tag);
*
* @param force Overwrite existing references
*
- * @return 0 or an error code
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code
* A tag object is written to the ODB, and a proper reference
* is written in the /refs/tags folder, pointing to it
*/
@@ -200,6 +204,9 @@ GIT_EXTERN(int) git_tag_create_frombuffer(
* this target object. If `force` is true and a reference
* already exists with the given name, it'll be replaced.
*
+ * The tag name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @param oid Pointer where to store the OID of the provided
* target object. If the tag already exists, this parameter
* will be filled with the oid of the existing pointed object
@@ -216,7 +223,7 @@ GIT_EXTERN(int) git_tag_create_frombuffer(
*
* @param force Overwrite existing references
*
- * @return 0 or an error code
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code
* A proper reference is written in the /refs/tags folder,
* pointing to the provided target object
*/
@@ -230,12 +237,15 @@ GIT_EXTERN(int) git_tag_create_lightweight(
/**
* Delete an existing tag reference.
*
+ * The tag name will be checked for validity.
+ * See `git_tag_create()` for rules about valid names.
+ *
* @param repo Repository where lives the tag
*
* @param tag_name Name of the tag to be deleted;
* this name is validated for consistency.
*
- * @return 0 or an error code
+ * @return 0 on success, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_tag_delete(
git_repository *repo,
diff --git a/include/git2/transport.h b/include/git2/transport.h
index 61726922f..00beb4472 100644
--- a/include/git2/transport.h
+++ b/include/git2/transport.h
@@ -82,6 +82,7 @@ typedef enum {
typedef void (*git_transport_message_cb)(const char *str, int len, void *data);
typedef struct git_transport {
+ unsigned int version;
/* Set progress and error callbacks */
int (*set_callbacks)(struct git_transport *transport,
git_transport_message_cb progress_cb,
@@ -140,6 +141,9 @@ typedef struct git_transport {
void (*free)(struct git_transport *transport);
} git_transport;
+#define GIT_TRANSPORT_VERSION 1
+#define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION}
+
/**
* Function to use to create a transport from a URL. The transport database
* is scanned to find a transport that implements the scheme of the URI (i.e.
@@ -284,6 +288,7 @@ typedef int (*git_smart_subtransport_cb)(
typedef struct git_smart_subtransport_definition {
/* The function to use to create the git_smart_subtransport */
git_smart_subtransport_cb callback;
+
/* True if the protocol is stateless; false otherwise. For example,
* http:// is stateless, but git:// is not. */
unsigned rpc : 1;
diff --git a/src/checkout.c b/src/checkout.c
index a3166bfa5..33de7adf3 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -203,21 +203,25 @@ static int checkout_blob(
return error;
}
-static int retrieve_symlink_caps(git_repository *repo, bool *can_symlink)
+static int retrieve_symlink_caps(git_repository *repo, bool *out)
{
git_config *cfg;
+ int can_symlink = 0;
int error;
if (git_repository_config__weakptr(&cfg, repo) < 0)
return -1;
- error = git_config_get_bool((int *)can_symlink, cfg, "core.symlinks");
+ error = git_config_get_bool(&can_symlink, cfg, "core.symlinks");
/* If "core.symlinks" is not found anywhere, default to true. */
if (error == GIT_ENOTFOUND) {
- *can_symlink = true;
+ can_symlink = true;
error = 0;
}
+
+ if (error >= 0)
+ *out = can_symlink;
return error;
}
@@ -228,7 +232,7 @@ static void normalize_options(
assert(normalized);
if (!proposed)
- memset(normalized, 0, sizeof(git_checkout_opts));
+ GIT_INIT_STRUCTURE(normalized, GIT_CHECKOUT_OPTS_VERSION);
else
memmove(normalized, proposed, sizeof(git_checkout_opts));
@@ -607,7 +611,7 @@ int git_checkout_index(
git_checkout_opts *opts)
{
git_diff_list *diff = NULL;
- git_diff_options diff_opts = {0};
+ git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
git_checkout_opts checkout_opts;
checkout_diff_data data;
git_buf workdir = GIT_BUF_INIT;
@@ -617,6 +621,8 @@ int git_checkout_index(
assert(repo);
+ GITERR_CHECK_VERSION(opts, GIT_CHECKOUT_OPTS_VERSION, "git_checkout_opts");
+
if ((error = git_repository__ensure_not_bare(repo, "checkout")) < 0)
return error;
diff --git a/src/common.h b/src/common.h
index a35239e3d..211e5b543 100644
--- a/src/common.h
+++ b/src/common.h
@@ -61,9 +61,38 @@ void giterr_set(int error_class, const char *string, ...);
/**
* Set the error message for a regex failure, using the internal regex
- * error code lookup.
+ * error code lookup and return a libgit error code.
*/
-void giterr_set_regex(const regex_t *regex, int error_code);
+int giterr_set_regex(const regex_t *regex, int error_code);
+
+/**
+ * Check a versioned structure for validity
+ */
+GIT_INLINE(int) giterr__check_version(const void *structure, unsigned int expected_max, const char *name)
+{
+ unsigned int actual;
+
+ if (!structure)
+ return 0;
+
+ actual = *(const unsigned int*)structure;
+ if (actual > 0 && actual <= expected_max)
+ return 0;
+
+ giterr_set(GITERR_INVALID, "Invalid version %d on %s", actual, name);
+ return -1;
+}
+#define GITERR_CHECK_VERSION(S,V,N) if (giterr__check_version(S,V,N) < 0) return -1
+
+/**
+ * Initialize a structure with a version.
+ */
+GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int version)
+{
+ memset(structure, 0, len);
+ *((int*)structure) = version;
+}
+#define GIT_INIT_STRUCTURE(S,V) git__init_structure(S, sizeof(*S), V)
/* NOTE: other giterr functions are in the public errors.h header file */
diff --git a/src/config.c b/src/config.c
index 6347f7df7..d422447cf 100644
--- a/src/config.c
+++ b/src/config.c
@@ -259,6 +259,8 @@ int git_config_add_backend(
assert(cfg && file);
+ GITERR_CHECK_VERSION(file, GIT_CONFIG_BACKEND_VERSION, "git_config_backend");
+
if ((result = file->open(file, level)) < 0)
return result;
diff --git a/src/config_cache.c b/src/config_cache.c
index ca9602e56..244202351 100644
--- a/src/config_cache.c
+++ b/src/config_cache.c
@@ -24,7 +24,7 @@ struct map_data {
* core.eol
* Sets the line ending type to use in the working directory for
* files that have the text property set. Alternatives are lf, crlf
- * and native, which uses the platform’s native line ending. The default
+ * and native, which uses the platform's native line ending. The default
* value is native. See gitattributes(5) for more information on
* end-of-line conversion.
*/
diff --git a/src/config_file.c b/src/config_file.c
index 354a91986..6e29832d4 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -545,10 +545,10 @@ int git_config_file__ondisk(git_config_backend **out, const char *path)
{
diskfile_backend *backend;
- backend = git__malloc(sizeof(diskfile_backend));
+ backend = git__calloc(1, sizeof(diskfile_backend));
GITERR_CHECK_ALLOC(backend);
- memset(backend, 0x0, sizeof(diskfile_backend));
+ backend->parent.version = GIT_CONFIG_BACKEND_VERSION;
backend->file_path = git__strdup(path);
GITERR_CHECK_ALLOC(backend->file_path);
diff --git a/src/delta-apply.c b/src/delta-apply.c
index 815ca8f16..85e2ef88f 100644
--- a/src/delta-apply.c
+++ b/src/delta-apply.c
@@ -36,6 +36,19 @@ static int hdr_sz(
return 0;
}
+int git__delta_read_header(
+ const unsigned char *delta,
+ size_t delta_len,
+ size_t *base_sz,
+ size_t *res_sz)
+{
+ const unsigned char *delta_end = delta + delta_len;
+ if ((hdr_sz(base_sz, &delta, delta_end) < 0) ||
+ (hdr_sz(res_sz, &delta, delta_end) < 0))
+ return -1;
+ return 0;
+}
+
int git__delta_apply(
git_rawobj *out,
const unsigned char *base,
diff --git a/src/delta-apply.h b/src/delta-apply.h
index 66fa76d43..9aea4ac9f 100644
--- a/src/delta-apply.h
+++ b/src/delta-apply.h
@@ -30,4 +30,21 @@ extern int git__delta_apply(
const unsigned char *delta,
size_t delta_len);
+/**
+ * Read the header of a git binary delta.
+ *
+ * @param delta the delta to execute copy/insert instructions from.
+ * @param delta_len total number of bytes in the delta.
+ * @param base_sz pointer to store the base size field.
+ * @param res_sz pointer to store the result size field.
+ * @return
+ * - 0 on a successful decoding the header.
+ * - GIT_ERROR if the delta is corrupt.
+ */
+extern int git__delta_read_header(
+ const unsigned char *delta,
+ size_t delta_len,
+ size_t *base_sz,
+ size_t *res_sz);
+
#endif
diff --git a/src/diff.c b/src/diff.c
index 86f76f9c0..c4bfc3687 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -285,7 +285,7 @@ static git_diff_list *git_diff_list_alloc(
goto fail;
if (diff->opts.flags & GIT_DIFF_REVERSE) {
- char *swap = diff->opts.old_prefix;
+ const char *swap = diff->opts.old_prefix;
diff->opts.old_prefix = diff->opts.new_prefix;
diff->opts.new_prefix = swap;
}
@@ -755,14 +755,14 @@ fail:
return error;
}
-
#define DIFF_FROM_ITERATORS(MAKE_FIRST, MAKE_SECOND) do { \
git_iterator *a = NULL, *b = NULL; \
char *pfx = opts ? git_pathspec_prefix(&opts->pathspec) : NULL; \
- if (!(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \
+ GITERR_CHECK_VERSION(opts, GIT_DIFF_OPTIONS_VERSION, "git_diff_options"); \
+ if (!(error = MAKE_FIRST) && !(error = MAKE_SECOND)) \
error = diff_from_iterators(diff, repo, a, b, opts); \
git__free(pfx); git_iterator_free(a); git_iterator_free(b); \
- } while (0)
+} while (0)
int git_diff_tree_to_tree(
git_diff_list **diff,
diff --git a/src/diff.h b/src/diff.h
index 1e3be7593..f93bab18d 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -61,5 +61,6 @@ extern bool git_diff_delta__should_skip(
extern int git_diff__oid_for_file(
git_repository *, const char *, uint16_t, git_off_t, git_oid *);
+
#endif
diff --git a/src/diff_output.c b/src/diff_output.c
index e137fd0f2..b18255d58 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -1266,6 +1266,8 @@ int git_diff_blobs(
git_diff_delta delta;
git_diff_patch patch;
+ GITERR_CHECK_VERSION(options, GIT_DIFF_OPTIONS_VERSION, "git_diff_options");
+
if (options && (options->flags & GIT_DIFF_REVERSE)) {
git_blob *swap = old_blob;
old_blob = new_blob;
diff --git a/src/diff_tform.c b/src/diff_tform.c
index 987d4b8e6..0c588594a 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -187,7 +187,8 @@ static int normalize_find_opts(
if (given != NULL)
memcpy(opts, given, sizeof(*opts));
else {
- memset(opts, 0, sizeof(*opts));
+ git_diff_find_options init = GIT_DIFF_FIND_OPTIONS_INIT;
+ memmove(opts, &init, sizeof(init));
opts->flags = GIT_DIFF_FIND_RENAMES;
@@ -198,6 +199,8 @@ static int normalize_find_opts(
opts->flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES;
}
+ GITERR_CHECK_VERSION(opts, GIT_DIFF_FIND_OPTIONS_VERSION, "git_diff_find_options");
+
/* some flags imply others */
if (opts->flags & GIT_DIFF_FIND_RENAMES_FROM_REWRITES)
diff --git a/src/errors.c b/src/errors.c
index ac7fa934d..e62507216 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -93,11 +93,18 @@ void giterr_set_str(int error_class, const char *string)
set_error(error_class, message);
}
-void giterr_set_regex(const regex_t *regex, int error_code)
+int giterr_set_regex(const regex_t *regex, int error_code)
{
char error_buf[1024];
regerror(error_code, regex, error_buf, sizeof(error_buf));
giterr_set_str(GITERR_REGEX, error_buf);
+
+ if (error_code == REG_NOMATCH)
+ return GIT_ENOTFOUND;
+ else if (error_code > REG_BADPAT)
+ return GIT_EINVALIDSPEC;
+ else
+ return -1;
}
void giterr_clear(void)
diff --git a/src/iterator.c b/src/iterator.c
index bd586ce99..0fdf0c69d 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -340,14 +340,6 @@ static int index_iterator__current(
index_iterator *ii = (index_iterator *)self;
const git_index_entry *ie = git_index_get_byindex(ii->index, ii->current);
- if (ie != NULL &&
- ii->base.end != NULL &&
- ITERATOR_PREFIXCMP(ii->base, ie->path, ii->base.end) > 0)
- {
- ii->current = git_index_entrycount(ii->index);
- ie = NULL;
- }
-
if (entry)
*entry = ie;
@@ -360,6 +352,29 @@ static int index_iterator__at_end(git_iterator *self)
return (ii->current >= git_index_entrycount(ii->index));
}
+static void index_iterator__skip_conflicts(
+ index_iterator *ii)
+{
+ size_t entrycount = git_index_entrycount(ii->index);
+ const git_index_entry *ie;
+
+ while (ii->current < entrycount) {
+ ie = git_index_get_byindex(ii->index, ii->current);
+
+ if (ie == NULL ||
+ (ii->base.end != NULL &&
+ ITERATOR_PREFIXCMP(ii->base, ie->path, ii->base.end) > 0)) {
+ ii->current = entrycount;
+ break;
+ }
+
+ if (git_index_entry_stage(ie) == 0)
+ break;
+
+ ii->current++;
+ }
+}
+
static int index_iterator__advance(
git_iterator *self, const git_index_entry **entry)
{
@@ -368,6 +383,8 @@ static int index_iterator__advance(
if (ii->current < git_index_entrycount(ii->index))
ii->current++;
+ index_iterator__skip_conflicts(ii);
+
return index_iterator__current(self, entry);
}
@@ -382,7 +399,9 @@ static int index_iterator__seek(git_iterator *self, const char *prefix)
static int index_iterator__reset(git_iterator *self)
{
index_iterator *ii = (index_iterator *)self;
- ii->current = 0;
+ ii->current = ii->base.start ?
+ git_index__prefix_position(ii->index, ii->base.start) : 0;
+ index_iterator__skip_conflicts(ii);
return 0;
}
@@ -406,7 +425,8 @@ int git_iterator_for_index_range(
ii->index = index;
ii->base.ignore_case = ii->index->ignore_case;
- ii->current = start ? git_index__prefix_position(ii->index, start) : 0;
+
+ index_iterator__reset((git_iterator *)ii);
*iter = (git_iterator *)ii;
diff --git a/src/notes.c b/src/notes.c
index dd36cc2fe..f96b5b139 100644
--- a/src/notes.c
+++ b/src/notes.c
@@ -11,6 +11,7 @@
#include "refs.h"
#include "config.h"
#include "iterator.h"
+#include "signature.h"
static int find_subtree_in_current_level(
git_tree **out,
diff --git a/src/object.c b/src/object.c
index f88c2ba50..d57b6468c 100644
--- a/src/object.c
+++ b/src/object.c
@@ -304,12 +304,6 @@ size_t git_object__size(git_otype type)
return git_objects_table[type].size;
}
-static int peel_error(int error, const char* msg)
-{
- giterr_set(GITERR_INVALID, "The given object cannot be peeled - %s", msg);
- return error;
-}
-
static int dereference_object(git_object **dereferenced, git_object *obj)
{
git_otype type = git_object_type(obj);
@@ -322,22 +316,46 @@ static int dereference_object(git_object **dereferenced, git_object *obj)
return git_tag_target(dereferenced, (git_tag*)obj);
case GIT_OBJ_BLOB:
- return peel_error(GIT_ERROR, "cannot dereference blob");
+ return GIT_ENOTFOUND;
case GIT_OBJ_TREE:
- return peel_error(GIT_ERROR, "cannot dereference tree");
+ return GIT_EAMBIGUOUS;
default:
- return peel_error(GIT_ENOTFOUND, "unexpected object type encountered");
+ return GIT_EINVALIDSPEC;
}
}
+static int peel_error(int error, const git_oid *oid, git_otype type)
+{
+ const char *type_name;
+ char hex_oid[GIT_OID_HEXSZ + 1];
+
+ type_name = git_object_type2string(type);
+
+ git_oid_fmt(hex_oid, oid);
+ hex_oid[GIT_OID_HEXSZ] = '\0';
+
+ giterr_set(GITERR_OBJECT, "The git_object of id '%s' can not be "
+ "successfully peeled into a %s (git_otype=%i).", hex_oid, type_name, type);
+
+ return error;
+}
+
int git_object_peel(
git_object **peeled,
const git_object *object,
git_otype target_type)
{
git_object *source, *deref = NULL;
+ int error;
+
+ if (target_type != GIT_OBJ_TAG &&
+ target_type != GIT_OBJ_COMMIT &&
+ target_type != GIT_OBJ_TREE &&
+ target_type != GIT_OBJ_BLOB &&
+ target_type != GIT_OBJ_ANY)
+ return GIT_EINVALIDSPEC;
assert(object && peeled);
@@ -346,7 +364,7 @@ int git_object_peel(
source = (git_object *)object;
- while (!dereference_object(&deref, source)) {
+ while (!(error = dereference_object(&deref, source))) {
if (source != object)
git_object_free(source);
@@ -371,6 +389,10 @@ int git_object_peel(
git_object_free(source);
git_object_free(deref);
- return -1;
+
+ if (error)
+ error = peel_error(error, git_object_id(object), target_type);
+
+ return error;
}
diff --git a/src/odb.c b/src/odb.c
index 23b3de9e3..2385a580c 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -369,6 +369,8 @@ static int add_backend_internal(git_odb *odb, git_odb_backend *backend, int prio
assert(odb && backend);
+ GITERR_CHECK_VERSION(backend, GIT_ODB_BACKEND_VERSION, "git_odb_backend");
+
/* Check if the backend is already owned by another ODB */
assert(!backend->odb || backend->odb == odb);
diff --git a/src/odb_loose.c b/src/odb_loose.c
index e2f1aec32..df86d903e 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -915,6 +915,7 @@ int git_odb_backend_loose(
backend = git__calloc(1, sizeof(loose_backend));
GITERR_CHECK_ALLOC(backend);
+ backend->parent.version = GIT_ODB_BACKEND_VERSION;
backend->objects_dir = git__strdup(objects_dir);
GITERR_CHECK_ALLOC(backend->objects_dir);
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 35bf1580d..b1a46c9ed 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -384,19 +384,18 @@ cleanup:
*
***********************************************************/
-/*
-int pack_backend__read_header(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid)
+static int pack_backend__read_header(size_t *len_p, git_otype *type_p, struct git_odb_backend *backend, const git_oid *oid)
{
- pack_location location;
+ struct git_pack_entry e;
+ int error;
- assert(obj && backend && oid);
+ assert(len_p && type_p && backend && oid);
- if (locate_packfile(&location, (struct pack_backend *)backend, oid) < 0)
- return GIT_ENOTFOUND;
+ if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < 0)
+ return error;
- return read_header_packed(obj, &location);
+ return git_packfile_resolve_header(len_p, type_p, e.p, e.offset);
}
-*/
static int pack_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
{
@@ -570,6 +569,7 @@ int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx)
backend = git__calloc(1, sizeof(struct pack_backend));
GITERR_CHECK_ALLOC(backend);
+ backend->parent.version = GIT_ODB_BACKEND_VERSION;
if (git_vector_init(&backend->packs, 1, NULL) < 0)
goto on_error;
@@ -579,7 +579,7 @@ int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx)
backend->parent.read = &pack_backend__read;
backend->parent.read_prefix = &pack_backend__read_prefix;
- backend->parent.read_header = NULL;
+ backend->parent.read_header = &pack_backend__read_header;
backend->parent.exists = &pack_backend__exists;
backend->parent.foreach = &pack_backend__foreach;
backend->parent.free = &pack_backend__free;
@@ -602,6 +602,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend = git__calloc(1, sizeof(struct pack_backend));
GITERR_CHECK_ALLOC(backend);
+ backend->parent.version = GIT_ODB_BACKEND_VERSION;
if (git_vector_init(&backend->packs, 8, packfile_sort__cb) < 0 ||
git_buf_joinpath(&path, objects_dir, "pack") < 0)
@@ -616,7 +617,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend->parent.read = &pack_backend__read;
backend->parent.read_prefix = &pack_backend__read_prefix;
- backend->parent.read_header = NULL;
+ backend->parent.read_header = &pack_backend__read_header;
backend->parent.exists = &pack_backend__exists;
backend->parent.foreach = &pack_backend__foreach;
backend->parent.writepack = &pack_backend__writepack;
diff --git a/src/pack.c b/src/pack.c
index 01531d631..520e13828 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -277,6 +277,56 @@ int git_packfile_unpack_header(
return 0;
}
+int git_packfile_resolve_header(
+ size_t *size_p,
+ git_otype *type_p,
+ struct git_pack_file *p,
+ git_off_t offset)
+{
+ git_mwindow *w_curs = NULL;
+ git_off_t curpos = offset;
+ size_t size;
+ git_otype type;
+ git_off_t base_offset;
+ int error;
+
+ error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
+ git_mwindow_close(&w_curs);
+ if (error < 0)
+ return error;
+
+ if (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
+ size_t base_size;
+ git_rawobj delta;
+ base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
+ git_mwindow_close(&w_curs);
+ error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, size, type);
+ git_mwindow_close(&w_curs);
+ if (error < 0)
+ return error;
+ error = git__delta_read_header(delta.data, delta.len, &base_size, size_p);
+ git__free(delta.data);
+ if (error < 0)
+ return error;
+ } else
+ *size_p = size;
+
+ while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
+ curpos = base_offset;
+ error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
+ git_mwindow_close(&w_curs);
+ if (error < 0)
+ return error;
+ if (type != GIT_OBJ_OFS_DELTA && type != GIT_OBJ_REF_DELTA)
+ break;
+ base_offset = get_delta_base(p, &w_curs, &curpos, type, base_offset);
+ git_mwindow_close(&w_curs);
+ }
+ *type_p = type;
+
+ return error;
+}
+
static int packfile_unpack_delta(
git_rawobj *obj,
struct git_pack_file *p,
diff --git a/src/pack.h b/src/pack.h
index 3355cd21f..188ea2bbd 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -93,6 +93,12 @@ int git_packfile_unpack_header(
git_mwindow **w_curs,
git_off_t *curpos);
+int git_packfile_resolve_header(
+ size_t *size_p,
+ git_otype *type_p,
+ struct git_pack_file *p,
+ git_off_t offset);
+
int git_packfile_unpack(git_rawobj *obj, struct git_pack_file *p, git_off_t *obj_offset);
int packfile_unpack_compressed(
git_rawobj *obj,
diff --git a/src/reflog.c b/src/reflog.c
index ac481fb81..df799b113 100644
--- a/src/reflog.c
+++ b/src/reflog.c
@@ -340,21 +340,29 @@ cleanup:
int git_reflog_rename(git_reference *ref, const char *new_name)
{
- int error = -1, fd;
+ int error, fd;
git_buf old_path = GIT_BUF_INIT;
git_buf new_path = GIT_BUF_INIT;
git_buf temp_path = GIT_BUF_INIT;
+ git_buf normalized = GIT_BUF_INIT;
assert(ref && new_name);
+ if ((error = git_reference__normalize_name(
+ &normalized, new_name, GIT_REF_FORMAT_ALLOW_ONELEVEL)) < 0)
+ goto cleanup;
+
+ error = -1;
+
if (git_buf_joinpath(&temp_path, git_reference_owner(ref)->path_repository, GIT_REFLOG_DIR) < 0)
return -1;
if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), ref->name) < 0)
goto cleanup;
- if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path), new_name) < 0)
- goto cleanup;
+ if (git_buf_joinpath(&new_path,
+ git_buf_cstr(&temp_path), git_buf_cstr(&normalized)) < 0)
+ goto cleanup;
/*
* Move the reflog to a temporary place. This two-phase renaming is required
@@ -386,6 +394,7 @@ cleanup:
git_buf_free(&temp_path);
git_buf_free(&old_path);
git_buf_free(&new_path);
+ git_buf_free(&normalized);
return error;
}
diff --git a/src/refs.c b/src/refs.c
index 76c9f42ba..85813096b 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -1215,11 +1215,11 @@ int git_reference_symbolic_create(
git_reference *ref = NULL;
int error;
- if (git_reference__normalize_name_lax(
+ if ((error = git_reference__normalize_name_lax(
normalized,
sizeof(normalized),
- name) < 0)
- return -1;
+ name)) < 0)
+ return error;
if ((error = reference_can_write(repo, normalized, NULL, force)) < 0)
return error;
@@ -1255,11 +1255,11 @@ int git_reference_create(
git_reference *ref = NULL;
char normalized[GIT_REFNAME_MAX];
- if (git_reference__normalize_name_lax(
+ if ((error = git_reference__normalize_name_lax(
normalized,
sizeof(normalized),
- name) < 0)
- return -1;
+ name)) < 0)
+ return error;
if ((error = reference_can_write(repo, normalized, NULL, force)) < 0)
return error;
@@ -1330,6 +1330,7 @@ int git_reference_set_target(git_reference *ref, const git_oid *id)
*/
int git_reference_symbolic_set_target(git_reference *ref, const char *target)
{
+ int error;
char normalized[GIT_REFNAME_MAX];
if ((ref->flags & GIT_REF_SYMBOLIC) == 0) {
@@ -1338,11 +1339,11 @@ int git_reference_symbolic_set_target(git_reference *ref, const char *target)
return -1;
}
- if (git_reference__normalize_name_lax(
+ if ((error = git_reference__normalize_name_lax(
normalized,
sizeof(normalized),
- target))
- return -1;
+ target)) < 0)
+ return error;
git__free(ref->target.symbolic);
ref->target.symbolic = git__strdup(normalized);
@@ -1363,12 +1364,12 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
GIT_REF_FORMAT_ALLOW_ONELEVEL
: GIT_REF_FORMAT_NORMAL;
- if (git_reference_normalize_name(
+ if ((result = git_reference_normalize_name(
normalized,
sizeof(normalized),
new_name,
- normalization_flags) < 0)
- return -1;
+ normalization_flags)) < 0)
+ return result;
if ((result = reference_can_write(ref->owner, normalized, ref->name, force)) < 0)
return result;
@@ -1645,7 +1646,7 @@ int git_reference__normalize_name(
// Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100
char *current;
- int segment_len, segments_count = 0, error = -1;
+ int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC;
unsigned int process_flags;
bool normalize = (buf != NULL);
assert(name);
@@ -1677,8 +1678,10 @@ int git_reference__normalize_name(
git_buf_truncate(buf,
cur_len + segment_len + (segments_count ? 1 : 0));
- if (git_buf_oom(buf))
+ if (git_buf_oom(buf)) {
+ error = -1;
goto cleanup;
+ }
}
segments_count++;
@@ -1721,7 +1724,7 @@ int git_reference__normalize_name(
error = 0;
cleanup:
- if (error)
+ if (error == GIT_EINVALIDSPEC)
giterr_set(
GITERR_REFERENCE,
"The given reference name '%s' is not valid", name);
@@ -1962,8 +1965,12 @@ int git_reference__is_valid_name(
const char *refname,
unsigned int flags)
{
+ int error;
+
+ error = git_reference__normalize_name(NULL, refname, flags) == 0;
giterr_clear();
- return git_reference__normalize_name(NULL, refname, flags) == 0;
+
+ return error;
}
int git_reference_is_valid_name(
diff --git a/src/remote.c b/src/remote.c
index c84911aa1..5b75e510c 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -57,6 +57,32 @@ static int download_tags_value(git_remote *remote, git_config *cfg)
return error;
}
+static int ensure_remote_name_is_valid(const char *name)
+{
+ git_buf buf = GIT_BUF_INIT;
+ git_refspec refspec;
+ int error = -1;
+
+ if (!name || *name == '\0')
+ goto cleanup;
+
+ git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", name);
+ error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
+
+ git_buf_free(&buf);
+ git_refspec__free(&refspec);
+
+cleanup:
+ if (error) {
+ giterr_set(
+ GITERR_CONFIG,
+ "'%s' is not a valid remote name.", name);
+ error = GIT_EINVALIDSPEC;
+ }
+
+ return error;
+}
+
int git_remote_new(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
{
git_remote *remote;
@@ -79,6 +105,12 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *name, con
GITERR_CHECK_ALLOC(remote->url);
if (name != NULL) {
+ int error;
+ if ((error = ensure_remote_name_is_valid(name)) < 0) {
+ git_remote_free(remote);
+ return error;
+ }
+
remote->name = git__strdup(name);
GITERR_CHECK_ALLOC(remote->name);
}
@@ -111,6 +143,9 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
assert(out && repo && name);
+ if ((error = ensure_remote_name_is_valid(name)) < 0)
+ return error;
+
if (git_repository_config__weakptr(&config, repo) < 0)
return -1;
@@ -212,30 +247,6 @@ cleanup:
return error;
}
-static int ensure_remote_name_is_valid(const char *name)
-{
- git_buf buf = GIT_BUF_INIT;
- git_refspec refspec;
- int error = -1;
-
- if (!name || *name == '\0')
- goto cleanup;
-
- git_buf_printf(&buf, "refs/heads/test:refs/remotes/%s/test", name);
- error = git_refspec__parse(&refspec, git_buf_cstr(&buf), true);
-
- git_buf_free(&buf);
- git_refspec__free(&refspec);
-
-cleanup:
- if (error)
- giterr_set(
- GITERR_CONFIG,
- "'%s' is not a valid remote name.", name);
-
- return error;
-}
-
static int update_config_refspec(
git_config *config,
const char *remote_name,
@@ -279,8 +290,8 @@ int git_remote_save(const git_remote *remote)
assert(remote);
- if (ensure_remote_name_is_valid(remote->name) < 0)
- return -1;
+ if ((error = ensure_remote_name_is_valid(remote->name)) < 0)
+ return error;
if (git_repository_config__weakptr(&config, remote->repo) < 0)
return -1;
@@ -958,6 +969,10 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
int git_remote_add(git_remote **out, git_repository *repo, const char *name, const char *url)
{
git_buf buf = GIT_BUF_INIT;
+ int error;
+
+ if ((error = ensure_remote_name_is_valid(name)) < 0)
+ return error;
if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
return -1;
@@ -985,10 +1000,12 @@ void git_remote_check_cert(git_remote *remote, int check)
remote->check_cert = check;
}
-void git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks)
+int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks)
{
assert(remote && callbacks);
+ GITERR_CHECK_VERSION(callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
+
memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks));
if (remote->transport && remote->transport->set_callbacks)
@@ -996,6 +1013,8 @@ void git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callback
remote->callbacks.progress,
NULL,
remote->callbacks.payload);
+
+ return 0;
}
void git_remote_set_cred_acquire_cb(
@@ -1011,6 +1030,8 @@ int git_remote_set_transport(git_remote *remote, git_transport *transport)
{
assert(remote && transport);
+ GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport");
+
if (remote->transport) {
giterr_set(GITERR_NET, "A transport is already bound to this remote");
return -1;
diff --git a/src/repository.c b/src/repository.c
index b49b49b7a..10ed12b64 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1151,9 +1151,8 @@ static int repo_init_create_origin(git_repository *repo, const char *url)
int git_repository_init(
git_repository **repo_out, const char *path, unsigned is_bare)
{
- git_repository_init_options opts;
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
- memset(&opts, 0, sizeof(opts));
opts.flags = GIT_REPOSITORY_INIT_MKPATH; /* don't love this default */
if (is_bare)
opts.flags |= GIT_REPOSITORY_INIT_BARE;
@@ -1171,6 +1170,8 @@ int git_repository_init_ext(
assert(out && given_repo && opts);
+ GITERR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options");
+
error = repo_init_directories(&repo_path, &wd_path, given_repo, opts);
if (error < 0)
goto cleanup;
diff --git a/src/reset.c b/src/reset.c
index d410a8806..17b4b900c 100644
--- a/src/reset.c
+++ b/src/reset.c
@@ -69,7 +69,7 @@ int git_reset(
git_index *index = NULL;
git_tree *tree = NULL;
int error = -1;
- git_checkout_opts opts;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
assert(repo && target);
assert(reset_type == GIT_RESET_SOFT
@@ -136,7 +136,6 @@ int git_reset(
goto cleanup;
}
- memset(&opts, 0, sizeof(opts));
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
if (git_checkout_index(repo, NULL, &opts) < 0) {
diff --git a/src/revparse.c b/src/revparse.c
index 308b92923..ade03d0e4 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -13,12 +13,6 @@
#include "git2.h"
-static int revspec_error(const char *revspec)
-{
- giterr_set(GITERR_INVALID, "Failed to parse revision specifier - Invalid pattern '%s'", revspec);
- return -1;
-}
-
static int disambiguate_refname(git_reference **out, git_repository *repo, const char *refname)
{
int error, i;
@@ -51,7 +45,7 @@ static int disambiguate_refname(git_reference **out, git_repository *repo, const
goto cleanup;
if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) {
- error = GIT_ENOTFOUND;
+ error = GIT_EINVALIDSPEC;
continue;
}
@@ -90,17 +84,18 @@ static int build_regex(regex_t *regex, const char *pattern)
if (*pattern == '\0') {
giterr_set(GITERR_REGEX, "Empty pattern");
- return -1;
+ return GIT_EINVALIDSPEC;
}
error = regcomp(regex, pattern, REG_EXTENDED);
if (!error)
return 0;
- giterr_set_regex(regex, error);
+ error = giterr_set_regex(regex, error);
+
regfree(regex);
- return -1;
+ return error;
}
static int maybe_describe(git_object**out, git_repository *repo, const char *spec)
@@ -174,7 +169,7 @@ static int try_parse_numeric(int *n, const char *curly_braces_content)
return 0;
}
-static int retrieve_previously_checked_out_branch_or_revision(git_object **out, git_reference **base_ref, git_repository *repo, const char *spec, const char *identifier, size_t position)
+static int retrieve_previously_checked_out_branch_or_revision(git_object **out, git_reference **base_ref, git_repository *repo, const char *identifier, size_t position)
{
git_reference *ref = NULL;
git_reflog *reflog = NULL;
@@ -189,7 +184,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out,
cur = position;
if (*identifier != '\0' || *base_ref != NULL)
- return revspec_error(spec);
+ return GIT_EINVALIDSPEC;
if (build_regex(&preg, "checkout: moving from (.*) to .*") < 0)
return -1;
@@ -332,6 +327,11 @@ static int retrieve_remote_tracking_reference(git_reference **base_ref, const ch
*base_ref = NULL;
}
+ if (!git_reference_is_branch(ref)) {
+ error = GIT_EINVALIDSPEC;
+ goto cleanup;
+ }
+
if ((error = git_branch_tracking(&tracking, ref)) < 0)
goto cleanup;
@@ -357,13 +357,13 @@ static int handle_at_syntax(git_object **out, git_reference **ref, const char *s
is_numeric = !try_parse_numeric(&parsed, curly_braces_content);
if (*curly_braces_content == '-' && (!is_numeric || parsed == 0)) {
- error = revspec_error(spec);
+ error = GIT_EINVALIDSPEC;
goto cleanup;
}
if (is_numeric) {
if (parsed < 0)
- error = retrieve_previously_checked_out_branch_or_revision(out, ref, repo, spec, git_buf_cstr(&identifier), -parsed);
+ error = retrieve_previously_checked_out_branch_or_revision(out, ref, repo, git_buf_cstr(&identifier), -parsed);
else
error = retrieve_revobject_from_reflog(out, ref, repo, git_buf_cstr(&identifier), parsed);
@@ -416,8 +416,9 @@ static int handle_caret_parent_syntax(git_object **out, git_object *obj, int n)
git_object *temp_commit = NULL;
int error;
- if (git_object_peel(&temp_commit, obj, GIT_OBJ_COMMIT) < 0)
- return -1;
+ if ((error = git_object_peel(&temp_commit, obj, GIT_OBJ_COMMIT)) < 0)
+ return (error == GIT_EAMBIGUOUS || error == GIT_ENOTFOUND) ?
+ GIT_EINVALIDSPEC : error;
if (n == 0) {
*out = temp_commit;
@@ -435,8 +436,9 @@ static int handle_linear_syntax(git_object **out, git_object *obj, int n)
git_object *temp_commit = NULL;
int error;
- if (git_object_peel(&temp_commit, obj, GIT_OBJ_COMMIT) < 0)
- return -1;
+ if ((error = git_object_peel(&temp_commit, obj, GIT_OBJ_COMMIT)) < 0)
+ return (error == GIT_EAMBIGUOUS || error == GIT_ENOTFOUND) ?
+ GIT_EINVALIDSPEC : error;
error = git_commit_nth_gen_ancestor((git_commit **)out, (git_commit*)temp_commit, n);
@@ -453,8 +455,8 @@ static int handle_colon_syntax(
int error = -1;
git_tree_entry *entry = NULL;
- if (git_object_peel(&tree, obj, GIT_OBJ_TREE) < 0)
- return -1;
+ if ((error = git_object_peel(&tree, obj, GIT_OBJ_TREE)) < 0)
+ return error == GIT_ENOTFOUND ? GIT_EINVALIDSPEC : error;
if (*path == '\0') {
*out = tree;
@@ -507,21 +509,21 @@ static int handle_grep_syntax(git_object **out, git_repository *repo, const git_
{
regex_t preg;
git_revwalk *walk = NULL;
- int error = -1;
+ int error;
- if (build_regex(&preg, pattern) < 0)
- return -1;
+ if ((error = build_regex(&preg, pattern)) < 0)
+ return error;
- if (git_revwalk_new(&walk, repo) < 0)
+ if ((error = git_revwalk_new(&walk, repo)) < 0)
goto cleanup;
git_revwalk_sorting(walk, GIT_SORT_TIME);
if (spec_oid == NULL) {
// TODO: @carlosmn: The glob should be refs/* but this makes git_revwalk_next() fails
- if (git_revwalk_push_glob(walk, GIT_REFS_HEADS_DIR "*") < 0)
+ if ((error = git_revwalk_push_glob(walk, GIT_REFS_HEADS_DIR "*")) < 0)
goto cleanup;
- } else if (git_revwalk_push(walk, spec_oid) < 0)
+ } else if ((error = git_revwalk_push(walk, spec_oid)) < 0)
goto cleanup;
error = walk_and_search(out, walk, &preg);
@@ -546,7 +548,7 @@ static int handle_caret_curly_syntax(git_object **out, git_object *obj, const ch
expected_type = parse_obj_type(curly_braces_content);
if (expected_type == GIT_OBJ_BAD)
- return -1;
+ return GIT_EINVALIDSPEC;
return git_object_peel(out, obj, expected_type);
}
@@ -560,13 +562,13 @@ static int extract_curly_braces_content(git_buf *buf, const char *spec, size_t *
(*pos)++;
if (spec[*pos] == '\0' || spec[*pos] != '{')
- return revspec_error(spec);
+ return GIT_EINVALIDSPEC;
(*pos)++;
while (spec[*pos] != '}') {
if (spec[*pos] == '\0')
- return revspec_error(spec);
+ return GIT_EINVALIDSPEC;
git_buf_putc(buf, spec[(*pos)++]);
}
@@ -610,7 +612,7 @@ static int extract_how_many(int *n, const char *spec, size_t *pos)
if (git__isdigit(spec[*pos])) {
if ((git__strtol32(&parsed, spec + *pos, &end_ptr, 10) < 0) < 0)
- return revspec_error(spec);
+ return GIT_EINVALIDSPEC;
accumulated += (parsed - 1);
*pos = end_ptr - spec;
@@ -655,7 +657,7 @@ static int ensure_base_rev_loaded(git_object **object, git_reference **reference
}
if (!allow_empty_identifier && identifier_len == 0)
- return revspec_error(spec);
+ return GIT_EINVALIDSPEC;
if (git_buf_put(&identifier, spec, identifier_len) < 0)
return -1;
@@ -666,12 +668,12 @@ static int ensure_base_rev_loaded(git_object **object, git_reference **reference
return error;
}
-static int ensure_base_rev_is_not_known_yet(git_object *object, const char *spec)
+static int ensure_base_rev_is_not_known_yet(git_object *object)
{
if (object == NULL)
return 0;
- return revspec_error(spec);
+ return GIT_EINVALIDSPEC;
}
static bool any_left_hand_identifier(git_object *object, git_reference *reference, size_t identifier_len)
@@ -688,12 +690,12 @@ static bool any_left_hand_identifier(git_object *object, git_reference *referenc
return false;
}
-static int ensure_left_hand_identifier_is_not_known_yet(git_object *object, git_reference *reference, const char *spec)
+static int ensure_left_hand_identifier_is_not_known_yet(git_object *object, git_reference *reference)
{
- if (!ensure_base_rev_is_not_known_yet(object, spec) && reference == NULL)
+ if (!ensure_base_rev_is_not_known_yet(object) && reference == NULL)
return 0;
- return revspec_error(spec);
+ return GIT_EINVALIDSPEC;
}
int git_revparse_single(git_object **out, git_repository *repo, const char *spec)
@@ -800,7 +802,7 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
if ((error = extract_curly_braces_content(&buf, spec, &pos)) < 0)
goto cleanup;
- if ((error = ensure_base_rev_is_not_known_yet(base_rev, spec)) < 0)
+ if ((error = ensure_base_rev_is_not_known_yet(base_rev)) < 0)
goto cleanup;
if ((error = handle_at_syntax(&temp_object, &reference, spec, identifier_len, repo, git_buf_cstr(&buf))) < 0)
@@ -815,7 +817,7 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
}
default:
- if ((error = ensure_left_hand_identifier_is_not_known_yet(base_rev, reference, spec)) < 0)
+ if ((error = ensure_left_hand_identifier_is_not_known_yet(base_rev, reference)) < 0)
goto cleanup;
pos++;
@@ -830,8 +832,13 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
error = 0;
cleanup:
- if (error)
+ if (error) {
+ if (error == GIT_EINVALIDSPEC)
+ giterr_set(GITERR_INVALID,
+ "Failed to parse revision specifier - Invalid pattern '%s'", spec);
+
git_object_free(base_rev);
+ }
git_reference_free(reference);
git_buf_free(&buf);
return error;
diff --git a/src/signature.c b/src/signature.c
index 0159488a4..7d043e6cf 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -264,7 +264,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
const char *line_end, *name_end, *email_end, *tz_start, *time_start;
int error = 0;
- memset(sig, 0x0, sizeof(git_signature));
+ memset(sig, 0, sizeof(git_signature));
if ((line_end = memchr(buffer, ender, buffer_end - buffer)) == NULL)
return signature_error("no newline given");
diff --git a/src/stash.c b/src/stash.c
index 107cbe3ca..e32d8fa31 100644
--- a/src/stash.c
+++ b/src/stash.c
@@ -14,6 +14,7 @@
#include "git2/stash.h"
#include "git2/status.h"
#include "git2/checkout.h"
+#include "signature.h"
static int create_error(int error, const char *msg)
{
@@ -229,7 +230,7 @@ static int build_untracked_tree(
{
git_tree *i_tree = NULL;
git_diff_list *diff = NULL;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
struct cb_data data = {0};
int error = -1;
@@ -315,7 +316,7 @@ static int build_workdir_tree(
git_repository *repo = git_index_owner(index);
git_tree *b_tree = NULL;
git_diff_list *diff = NULL, *diff2 = NULL;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
struct cb_data data = {0};
int error = -1;
@@ -471,9 +472,8 @@ static int ensure_there_are_changes_to_stash(
bool include_ignored_files)
{
int error;
- git_status_options opts;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
- memset(&opts, 0, sizeof(opts));
opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
if (include_untracked_files)
opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
@@ -498,9 +498,7 @@ static int reset_index_and_workdir(
git_commit *commit,
bool remove_untracked)
{
- git_checkout_opts opts;
-
- memset(&opts, 0, sizeof(git_checkout_opts));
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
opts.checkout_strategy =
GIT_CHECKOUT_UPDATE_MODIFIED | GIT_CHECKOUT_UPDATE_UNTRACKED;
diff --git a/src/status.c b/src/status.c
index c7dea2c71..1ad835adb 100644
--- a/src/status.c
+++ b/src/status.c
@@ -108,7 +108,7 @@ int git_status_foreach_ext(
void *payload)
{
int err = 0;
- git_diff_options diffopt;
+ git_diff_options diffopt = GIT_DIFF_OPTIONS_INIT;
git_diff_list *idx2head = NULL, *wd2idx = NULL;
git_tree *head = NULL;
git_status_show_t show =
@@ -117,6 +117,8 @@ int git_status_foreach_ext(
assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);
+ GITERR_CHECK_VERSION(opts, GIT_STATUS_OPTIONS_VERSION, "git_status_options");
+
if (show != GIT_STATUS_SHOW_INDEX_ONLY &&
(err = git_repository__ensure_not_bare(repo, "status")) < 0)
return err;
@@ -126,7 +128,6 @@ int git_status_foreach_ext(
!(err == GIT_ENOTFOUND || err == GIT_EORPHANEDHEAD))
return err;
- memset(&diffopt, 0, sizeof(diffopt));
memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec));
diffopt.flags = GIT_DIFF_INCLUDE_TYPECHANGE;
@@ -181,9 +182,8 @@ int git_status_foreach(
git_status_cb callback,
void *payload)
{
- git_status_options opts;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
- memset(&opts, 0, sizeof(opts));
opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED |
GIT_STATUS_OPT_INCLUDE_UNTRACKED |
@@ -224,16 +224,14 @@ int git_status_file(
const char *path)
{
int error;
- git_status_options opts;
- struct status_file_info sfi;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+ struct status_file_info sfi = {0};
assert(status_flags && repo && path);
- memset(&sfi, 0, sizeof(sfi));
if ((sfi.expected = git__strdup(path)) == NULL)
return -1;
- memset(&opts, 0, sizeof(opts));
opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED |
GIT_STATUS_OPT_INCLUDE_UNTRACKED |
diff --git a/src/submodule.c b/src/submodule.c
index c117255d4..21a1875c2 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -205,7 +205,7 @@ int git_submodule_add_setup(
git_config_backend *mods = NULL;
git_submodule *sm;
git_buf name = GIT_BUF_INIT, real_url = GIT_BUF_INIT;
- git_repository_init_options initopt;
+ git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT;
git_repository *subrepo = NULL;
assert(repo && url && path);
@@ -275,7 +275,6 @@ int git_submodule_add_setup(
* Old style: sub-repo goes directly into repo/<name>/.git/
*/
- memset(&initopt, 0, sizeof(initopt));
initopt.flags = GIT_REPOSITORY_INIT_MKPATH |
GIT_REPOSITORY_INIT_NO_REINIT;
initopt.origin_url = real_url.ptr;
@@ -1439,7 +1438,7 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
if (sm_repo != NULL) {
git_tree *sm_head;
- git_diff_options opt;
+ git_diff_options opt = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff;
/* the diffs below could be optimized with an early termination
@@ -1452,7 +1451,6 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
if ((error = git_repository_head_tree(&sm_head, sm_repo)) < 0)
return error;
- memset(&opt, 0, sizeof(opt));
if (sm->ignore == GIT_SUBMODULE_IGNORE_NONE)
opt.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
diff --git a/src/tag.c b/src/tag.c
index 606afd657..94915ad78 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -251,7 +251,7 @@ static int git_tag_create__internal(
error = retrieve_tag_reference_oid(oid, &ref_name, repo, tag_name);
if (error < 0 && error != GIT_ENOTFOUND)
- return -1;
+ goto cleanup;
/** Ensure the tag name doesn't conflict with an already existing
* reference unless overwriting has explictly been requested **/
@@ -269,6 +269,7 @@ static int git_tag_create__internal(
error = git_reference_create(&new_ref, repo, ref_name.ptr, oid, allow_ref_overwrite);
+cleanup:
git_reference_free(new_ref);
git_buf_free(&ref_name);
return error;
@@ -384,7 +385,7 @@ int git_tag_delete(git_repository *repo, const char *tag_name)
git_buf_free(&ref_name);
if (error < 0)
- return -1;
+ return error;
return git_reference_delete(tag_ref);
}
diff --git a/src/transports/local.c b/src/transports/local.c
index 62e8024b5..768daf3a8 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -403,11 +403,10 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param)
GIT_UNUSED(param);
- t = git__malloc(sizeof(transport_local));
+ t = git__calloc(1, sizeof(transport_local));
GITERR_CHECK_ALLOC(t);
- memset(t, 0x0, sizeof(transport_local));
-
+ t->parent.version = GIT_TRANSPORT_VERSION;
t->parent.connect = local_connect;
t->parent.negotiate_fetch = local_negotiate_fetch;
t->parent.download_pack = local_download_pack;
diff --git a/src/transports/smart.c b/src/transports/smart.c
index 94d389b52..5300a47c8 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -303,6 +303,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
t = git__calloc(sizeof(transport_smart), 1);
GITERR_CHECK_ALLOC(t);
+ t->parent.version = GIT_TRANSPORT_VERSION;
t->parent.set_callbacks = git_smart__set_callbacks;
t->parent.connect = git_smart__connect;
t->parent.close = git_smart__close;
diff --git a/src/tree.c b/src/tree.c
index fedf4b604..efb991df1 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -18,12 +18,33 @@ static bool valid_filemode(const int filemode)
{
return (filemode == GIT_FILEMODE_TREE
|| filemode == GIT_FILEMODE_BLOB
- || filemode == GIT_FILEMODE_BLOB_GROUP_WRITABLE
|| filemode == GIT_FILEMODE_BLOB_EXECUTABLE
|| filemode == GIT_FILEMODE_LINK
|| filemode == GIT_FILEMODE_COMMIT);
}
+GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
+{
+ /* Tree bits set, but it's not a commit */
+ if (filemode & GIT_FILEMODE_TREE && !(filemode & 0100000))
+ return GIT_FILEMODE_TREE;
+
+ /* If any of the x bits is set */
+ if (filemode & 0111)
+ return GIT_FILEMODE_BLOB_EXECUTABLE;
+
+ /* 16XXXX means commit */
+ if ((filemode & GIT_FILEMODE_COMMIT) == GIT_FILEMODE_COMMIT)
+ return GIT_FILEMODE_COMMIT;
+
+ /* 12XXXX means commit */
+ if ((filemode & GIT_FILEMODE_LINK) == GIT_FILEMODE_LINK)
+ return GIT_FILEMODE_LINK;
+
+ /* Otherwise, return a blob */
+ return GIT_FILEMODE_BLOB;
+}
+
static int valid_entry_name(const char *filename)
{
return *filename != '\0' &&
@@ -320,10 +341,11 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
git_tree_entry *entry;
int attr;
- if (git__strtol32(&attr, buffer, &buffer, 8) < 0 ||
- !buffer || !valid_filemode(attr))
+ if (git__strtol32(&attr, buffer, &buffer, 8) < 0 || !buffer)
return tree_error("Failed to parse tree. Can't parse filemode", NULL);
+ attr = normalize_filemode(attr); /* make sure to normalize the filemode */
+
if (*buffer++ != ' ')
return tree_error("Failed to parse tree. Object is corrupted", NULL);
@@ -529,19 +551,6 @@ static void sort_entries(git_treebuilder *bld)
git_vector_sort(&bld->entries);
}
-GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
-{
- /* 100664 mode is an early design mistake. Tree entries may bear
- * this mode in some old git repositories, but it's now deprecated.
- * We silently normalize while inserting new entries in a tree
- * being built.
- */
- if (filemode == GIT_FILEMODE_BLOB_GROUP_WRITABLE)
- return GIT_FILEMODE_BLOB;
-
- return filemode;
-}
-
int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
{
git_treebuilder *bld;
@@ -565,7 +574,7 @@ int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
if (append_entry(
bld, entry_src->filename,
&entry_src->oid,
- normalize_filemode((git_filemode_t)entry_src->attr)) < 0)
+ entry_src->attr) < 0)
goto on_error;
}
}
@@ -593,8 +602,6 @@ int git_treebuilder_insert(
if (!valid_filemode(filemode))
return tree_error("Failed to insert entry. Invalid filemode for file", filename);
- filemode = normalize_filemode(filemode);
-
if (!valid_entry_name(filename))
return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c
index b6d637223..a67765b26 100644
--- a/tests-clar/checkout/index.c
+++ b/tests-clar/checkout/index.c
@@ -25,7 +25,7 @@ void test_checkout_index__initialize(void)
{
git_tree *tree;
- memset(&g_opts, 0, sizeof(g_opts));
+ GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION);
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
g_repo = cl_git_sandbox_init("testrepo");
@@ -66,7 +66,7 @@ void test_checkout_index__cannot_checkout_a_bare_repository(void)
{
test_checkout_index__cleanup();
- memset(&g_opts, 0, sizeof(g_opts));
+ GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION);
g_repo = cl_git_sandbox_init("testrepo.git");
cl_git_fail(git_checkout_index(g_repo, NULL, NULL));
@@ -426,3 +426,21 @@ void test_checkout_index__can_overcome_name_clashes(void)
git_index_free(index);
}
+
+void test_checkout_index__validates_struct_version(void)
+{
+ const git_error *err;
+
+ g_opts.version = 1024;
+ cl_git_fail(git_checkout_index(g_repo, NULL, &g_opts));
+
+ err = giterr_last();
+ cl_assert_equal_i(err->klass, GITERR_INVALID);
+
+ g_opts.version = 0;
+ giterr_clear();
+ cl_git_fail(git_checkout_index(g_repo, NULL, &g_opts));
+
+ err = giterr_last();
+ cl_assert_equal_i(err->klass, GITERR_INVALID);
+}
diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c
index 534c46086..88dbe4ffc 100644
--- a/tests-clar/checkout/tree.c
+++ b/tests-clar/checkout/tree.c
@@ -11,7 +11,7 @@ void test_checkout_tree__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
- memset(&g_opts, 0, sizeof(g_opts));
+ GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION);
g_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
}
diff --git a/tests-clar/checkout/typechange.c b/tests-clar/checkout/typechange.c
index cd34885de..98c15bcb7 100644
--- a/tests-clar/checkout/typechange.c
+++ b/tests-clar/checkout/typechange.c
@@ -38,7 +38,7 @@ void test_checkout_typechange__checkout_typechanges(void)
{
int i;
git_object *obj;
- git_checkout_opts opts = {0};
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
diff --git a/tests-clar/commit/parse.c b/tests-clar/commit/parse.c
index bbb502cb5..8075f2619 100644
--- a/tests-clar/commit/parse.c
+++ b/tests-clar/commit/parse.c
@@ -149,7 +149,7 @@ void test_commit_parse__signature(void)
{
const char *str = passcase->string;
size_t len = strlen(passcase->string);
- struct git_signature person = {NULL, NULL, {0, 0}};
+ struct git_signature person = {0};
cl_git_pass(git_signature__parse(&person, &str, str + len, passcase->header, '\n'));
cl_assert(strcmp(passcase->name, person.name) == 0);
cl_assert(strcmp(passcase->email, person.email) == 0);
@@ -162,7 +162,7 @@ void test_commit_parse__signature(void)
{
const char *str = failcase->string;
size_t len = strlen(failcase->string);
- git_signature person = {NULL, NULL, {0, 0}};
+ git_signature person = {0};
cl_git_fail(git_signature__parse(&person, &str, str + len, failcase->header, '\n'));
git__free(person.name); git__free(person.email);
}
diff --git a/tests-clar/config/backend.c b/tests-clar/config/backend.c
new file mode 100644
index 000000000..65dbccc60
--- /dev/null
+++ b/tests-clar/config/backend.c
@@ -0,0 +1,21 @@
+#include "clar_libgit2.h"
+
+void test_config_backend__checks_version(void)
+{
+ git_config *cfg;
+ git_config_backend backend = GIT_CONFIG_BACKEND_INIT;
+ const git_error *err;
+
+ backend.version = 1024;
+
+ cl_git_pass(git_config_new(&cfg));
+ cl_git_fail(git_config_add_backend(cfg, &backend, 0, false));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+ giterr_clear();
+ backend.version = 1024;
+ cl_git_fail(git_config_add_backend(cfg, &backend, 0, false));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+}
diff --git a/tests-clar/diff/blob.c b/tests-clar/diff/blob.c
index 6a5645d4b..d7fdba0e6 100644
--- a/tests-clar/diff/blob.c
+++ b/tests-clar/diff/blob.c
@@ -12,7 +12,7 @@ void test_diff_blob__initialize(void)
g_repo = cl_git_sandbox_init("attr");
- memset(&opts, 0, sizeof(opts));
+ GIT_INIT_STRUCTURE(&opts, GIT_DIFF_OPTIONS_VERSION);
opts.context_lines = 1;
opts.interhunk_lines = 0;
@@ -313,3 +313,25 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
git_blob_free(old_d);
}
+
+void test_diff_blob__checks_options_version_too_low(void)
+{
+ const git_error *err;
+
+ opts.version = 0;
+ cl_git_fail(git_diff_blobs(
+ d, alien, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+}
+
+void test_diff_blob__checks_options_version_too_high(void)
+{
+ const git_error *err;
+
+ opts.version = 1024;
+ cl_git_fail(git_diff_blobs(
+ d, alien, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+}
diff --git a/tests-clar/diff/diff_helpers.h b/tests-clar/diff/diff_helpers.h
index 12591f63e..49c265285 100644
--- a/tests-clar/diff/diff_helpers.h
+++ b/tests-clar/diff/diff_helpers.h
@@ -48,3 +48,4 @@ extern int diff_foreach_via_iterator(
void *data);
extern void diff_print(FILE *fp, git_diff_list *diff);
+
diff --git a/tests-clar/diff/diffiter.c b/tests-clar/diff/diffiter.c
index 133392c21..306a13eb9 100644
--- a/tests-clar/diff/diffiter.c
+++ b/tests-clar/diff/diffiter.c
@@ -76,7 +76,7 @@ void test_diff_diffiter__iterate_files_2(void)
void test_diff_diffiter__iterate_files_and_hunks(void)
{
git_repository *repo = cl_git_sandbox_init("status");
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
size_t d, num_d;
int file_count = 0, hunk_count = 0;
@@ -129,7 +129,7 @@ void test_diff_diffiter__iterate_files_and_hunks(void)
void test_diff_diffiter__max_size_threshold(void)
{
git_repository *repo = cl_git_sandbox_init("status");
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
int file_count = 0, binary_count = 0, hunk_count = 0;
size_t d, num_d;
@@ -207,7 +207,7 @@ void test_diff_diffiter__max_size_threshold(void)
void test_diff_diffiter__iterate_all(void)
{
git_repository *repo = cl_git_sandbox_init("status");
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp = {0};
size_t d, num_d;
@@ -280,7 +280,7 @@ static void iterate_over_patch(git_diff_patch *patch, diff_expects *exp)
void test_diff_diffiter__iterate_randomly_while_saving_state(void)
{
git_repository *repo = cl_git_sandbox_init("status");
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp = {0};
git_diff_patch *patches[PATCH_CACHE];
@@ -441,3 +441,25 @@ void test_diff_diffiter__iterate_and_generate_patch_text(void)
git_diff_list_free(diff);
}
+
+void test_diff_diffiter__checks_options_version(void)
+{
+ git_repository *repo = cl_git_sandbox_init("status");
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_diff_list *diff = NULL;
+ const git_error *err;
+
+ opts.version = 0;
+ opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
+
+ cl_git_fail(git_diff_workdir_to_index(&diff, repo, NULL, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+ giterr_clear();
+ opts.version = 1024;
+ cl_git_fail(git_diff_workdir_to_index(&diff, repo, NULL, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+}
+
diff --git a/tests-clar/diff/index.c b/tests-clar/diff/index.c
index 9591e3457..267b3291c 100644
--- a/tests-clar/diff/index.c
+++ b/tests-clar/diff/index.c
@@ -20,7 +20,7 @@ void test_diff_index__0(void)
const char *b_commit = "0017bd4ab1ec3"; /* the start */
git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit);
git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit);
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp;
@@ -113,7 +113,7 @@ void test_diff_index__1(void)
const char *b_commit = "0017bd4ab1ec3"; /* the start */
git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit);
git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit);
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp;
@@ -140,3 +140,24 @@ void test_diff_index__1(void)
git_tree_free(a);
git_tree_free(b);
}
+
+void test_diff_index__checks_options_version(void)
+{
+ const char *a_commit = "26a125ee1bf";
+ git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit);
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_diff_list *diff;
+ const git_error *err;
+
+ opts.version = 0;
+ cl_git_fail(git_diff_index_to_tree(&diff, g_repo, a, NULL, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+ giterr_clear();
+ opts.version = 1024;
+ cl_git_fail(git_diff_index_to_tree(&diff, g_repo, a, NULL, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+}
+
diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c
index 0d57f8ff0..2995b4ef5 100644
--- a/tests-clar/diff/rename.c
+++ b/tests-clar/diff/rename.c
@@ -33,8 +33,8 @@ void test_diff_rename__match_oid(void)
const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a";
git_tree *old_tree, *new_tree;
git_diff_list *diff;
- git_diff_options diffopts = {0};
- git_diff_find_options opts;
+ git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
+ git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
diff_expects exp;
old_tree = resolve_commit_oid_to_tree(g_repo, old_sha);
@@ -43,7 +43,6 @@ void test_diff_rename__match_oid(void)
/* Must pass GIT_DIFF_INCLUDE_UNMODIFIED if you expect to emulate
* --find-copies-harder during rename transformion...
*/
- memset(&diffopts, 0, sizeof(diffopts));
diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED;
cl_git_pass(git_diff_tree_to_tree(
@@ -85,7 +84,6 @@ void test_diff_rename__match_oid(void)
* 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \
* 2bc7f351d20b53f1c72c16c4b036e491c478c49a
*/
- memset(&opts, 0, sizeof(opts));
opts.flags = GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED;
cl_git_pass(git_diff_find_similar(diff, &opts));
@@ -103,3 +101,35 @@ void test_diff_rename__match_oid(void)
git_tree_free(old_tree);
git_tree_free(new_tree);
}
+
+void test_diff_rename__checks_options_version(void)
+{
+ const char *old_sha = "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2";
+ const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a";
+ git_tree *old_tree, *new_tree;
+ git_diff_list *diff;
+ git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
+ git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
+ const git_error *err;
+
+ old_tree = resolve_commit_oid_to_tree(g_repo, old_sha);
+ new_tree = resolve_commit_oid_to_tree(g_repo, new_sha);
+ diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED;
+ cl_git_pass(git_diff_tree_to_tree(
+ &diff, g_repo, old_tree, new_tree, &diffopts));
+
+ opts.version = 0;
+ cl_git_fail(git_diff_find_similar(diff, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+ giterr_clear();
+ opts.version = 1024;
+ cl_git_fail(git_diff_find_similar(diff, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+ git_diff_list_free(diff);
+ git_tree_free(old_tree);
+ git_tree_free(new_tree);
+}
diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c
index 58dc4e6fa..442e53b25 100644
--- a/tests-clar/diff/tree.c
+++ b/tests-clar/diff/tree.c
@@ -19,7 +19,7 @@ void test_diff_tree__0(void)
const char *b_commit = "370fe9ec22";
const char *c_commit = "f5b0af1fb4f5c";
git_tree *a, *b, *c;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp;
@@ -175,7 +175,7 @@ void test_diff_tree__bare(void)
const char *a_commit = "8496071c1b46c85";
const char *b_commit = "be3563ae3f79";
git_tree *a, *b;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp;
@@ -264,7 +264,7 @@ void test_diff_tree__larger_hunks(void)
const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69";
const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10";
git_tree *a, *b;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
size_t d, num_d, h, num_h, l, num_l, header_len, line_len;
const git_diff_delta *delta;
@@ -319,3 +319,31 @@ void test_diff_tree__larger_hunks(void)
git_tree_free(a);
git_tree_free(b);
}
+
+void test_diff_tree__checks_options_version(void)
+{
+ const char *a_commit = "8496071c1b46c85";
+ const char *b_commit = "be3563ae3f79";
+ git_tree *a, *b;
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_diff_list *diff = NULL;
+ const git_error *err;
+
+ g_repo = cl_git_sandbox_init("testrepo.git");
+
+ cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL);
+ cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL);
+
+ opts.version = 0;
+ cl_git_fail(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+ giterr_clear();
+ opts.version = 1024;
+ cl_git_fail(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts));
+ err = giterr_last();
+
+ git_tree_free(a);
+ git_tree_free(b);
+}
diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c
index 57c88c3e5..10d58b118 100644
--- a/tests-clar/diff/workdir.c
+++ b/tests-clar/diff/workdir.c
@@ -15,7 +15,7 @@ void test_diff_workdir__cleanup(void)
void test_diff_workdir__to_index(void)
{
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp;
int use_iterator;
@@ -69,7 +69,7 @@ void test_diff_workdir__to_tree(void)
const char *a_commit = "26a125ee1bf"; /* the current HEAD */
const char *b_commit = "0017bd4ab1ec3"; /* the start */
git_tree *a, *b;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
git_diff_list *diff2 = NULL;
diff_expects exp;
@@ -202,7 +202,7 @@ void test_diff_workdir__to_tree(void)
void test_diff_workdir__to_index_with_pathspec(void)
{
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp;
char *pathspec = NULL;
@@ -420,7 +420,7 @@ void test_diff_workdir__filemode_changes_with_filemode_false(void)
void test_diff_workdir__head_index_and_workdir_all_differ(void)
{
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff_i2t = NULL, *diff_w2i = NULL;
diff_expects exp;
char *pathspec = "staged_changes_modified_file";
@@ -518,7 +518,7 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void)
void test_diff_workdir__eof_newline_changes(void)
{
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp;
char *pathspec = "current_file";
@@ -678,7 +678,7 @@ void test_diff_workdir__larger_hunks(void)
const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69";
const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10";
git_tree *a, *b;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
size_t i, d, num_d, h, num_h, l, num_l, header_len, line_len;
g_repo = cl_git_sandbox_init("diff");
@@ -763,7 +763,7 @@ void test_diff_workdir__submodules(void)
{
const char *a_commit = "873585b94bdeabccea991ea5e3ec1a277895b698";
git_tree *a;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
diff_expects exp;
@@ -822,7 +822,7 @@ void test_diff_workdir__submodules(void)
void test_diff_workdir__cannot_diff_against_a_bare_repository(void)
{
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff_list *diff = NULL;
git_tree *tree;
@@ -843,7 +843,7 @@ void test_diff_workdir__to_null_tree(void)
{
git_diff_list *diff;
diff_expects exp;
- git_diff_options opts = {0};
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
opts.flags = GIT_DIFF_INCLUDE_UNTRACKED |
GIT_DIFF_RECURSE_UNTRACKED_DIRS;
@@ -861,3 +861,23 @@ void test_diff_workdir__to_null_tree(void)
git_diff_list_free(diff);
}
+
+void test_diff_workdir__checks_options_version(void)
+{
+ git_diff_list *diff;
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ const git_error *err;
+
+ g_repo = cl_git_sandbox_init("status");
+
+ opts.version = 0;
+ cl_git_fail(git_diff_workdir_to_tree(&diff, g_repo, NULL, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+ giterr_clear();
+ opts.version = 1024;
+ cl_git_fail(git_diff_workdir_to_tree(&diff, g_repo, NULL, &opts));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+}
diff --git a/tests-clar/network/fetch.c b/tests-clar/network/fetch.c
index 84c947291..a5e2c02a7 100644
--- a/tests-clar/network/fetch.c
+++ b/tests-clar/network/fetch.c
@@ -36,10 +36,9 @@ static void progress(const git_transfer_progress *stats, void *payload)
static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n)
{
git_remote *remote;
- git_remote_callbacks callbacks;
+ git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT;
size_t bytes_received = 0;
- memset(&callbacks, 0, sizeof(git_remote_callbacks));
callbacks.update_tips = update_tips;
counter = 0;
@@ -79,6 +78,8 @@ void test_network_fetch__no_tags_http(void)
static void transferProgressCallback(const git_transfer_progress *stats, void *payload)
{
bool *invoked = (bool *)payload;
+
+ GIT_UNUSED(stats);
*invoked = true;
}
diff --git a/tests-clar/network/push_util.h b/tests-clar/network/push_util.h
index 2f4dffce4..759122aa6 100644
--- a/tests-clar/network/push_util.h
+++ b/tests-clar/network/push_util.h
@@ -11,7 +11,8 @@ extern const git_oid OID_ZERO;
* record data in a record_callbacks_data instance.
* @param data pointer to a record_callbacks_data instance
*/
-#define RECORD_CALLBACKS_INIT(data) { NULL, NULL, record_update_tips_cb, data }
+#define RECORD_CALLBACKS_INIT(data) \
+ { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, record_update_tips_cb, data }
typedef struct {
char *name;
diff --git a/tests-clar/network/remoterename.c b/tests-clar/network/remoterename.c
index b14554572..bd582314d 100644
--- a/tests-clar/network/remoterename.c
+++ b/tests-clar/network/remoterename.c
@@ -121,7 +121,9 @@ void test_network_remoterename__new_name_can_contain_dots(void)
void test_network_remoterename__new_name_must_conform_to_reference_naming_conventions(void)
{
- cl_git_fail(git_remote_rename(_remote, "new@{name", dont_call_me_cb, NULL));
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC,
+ git_remote_rename(_remote, "new@{name", dont_call_me_cb, NULL));
}
void test_network_remoterename__renamed_name_is_persisted(void)
diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c
index 14fda1670..70df001e7 100644
--- a/tests-clar/network/remotes.c
+++ b/tests-clar/network/remotes.c
@@ -202,6 +202,11 @@ void test_network_remotes__loading_a_missing_remote_returns_ENOTFOUND(void)
cl_assert_equal_i(GIT_ENOTFOUND, git_remote_load(&_remote, _repo, "just-left-few-minutes-ago"));
}
+void test_network_remotes__loading_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_remote_load(&_remote, _repo, "Inv@{id"));
+}
+
/*
* $ git remote add addtest http://github.com/libgit2/libgit2
*
@@ -229,8 +234,9 @@ void test_network_remotes__cannot_add_a_nameless_remote(void)
{
git_remote *remote;
- cl_git_fail(git_remote_add(&remote, _repo, NULL, "git://github.com/libgit2/libgit2"));
- cl_git_fail(git_remote_add(&remote, _repo, "", "git://github.com/libgit2/libgit2"));
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC,
+ git_remote_add(&remote, _repo, NULL, "git://github.com/libgit2/libgit2"));
}
void test_network_remotes__cannot_save_a_nameless_remote(void)
@@ -239,13 +245,34 @@ void test_network_remotes__cannot_save_a_nameless_remote(void)
cl_git_pass(git_remote_new(&remote, _repo, NULL, "git://github.com/libgit2/libgit2", NULL));
- cl_git_fail(git_remote_save(remote));
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_remote_save(remote));
git_remote_free(remote);
+}
+
+void test_network_remotes__cannot_add_a_remote_with_an_invalid_name(void)
+{
+ git_remote *remote;
- cl_git_pass(git_remote_new(&remote, _repo, "", "git://github.com/libgit2/libgit2", NULL));
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC,
+ git_remote_add(&remote, _repo, "Inv@{id", "git://github.com/libgit2/libgit2"));
- cl_git_fail(git_remote_save(remote));
- git_remote_free(remote);
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC,
+ git_remote_add(&remote, _repo, "", "git://github.com/libgit2/libgit2"));
+}
+
+void test_network_remotes__cannot_initialize_a_remote_with_an_invalid_name(void)
+{
+ git_remote *remote;
+
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC,
+ git_remote_new(&remote, _repo, "Inv@{id", "git://github.com/libgit2/libgit2", NULL));
+
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC,
+ git_remote_new(&remote, _repo, "", "git://github.com/libgit2/libgit2", NULL));
}
void test_network_remotes__tagopt(void)
@@ -279,3 +306,23 @@ void test_network_remotes__cannot_load_with_an_empty_url(void)
cl_git_fail(git_remote_load(&remote, _repo, "empty-remote-url"));
cl_assert(giterr_last()->klass == GITERR_INVALID);
}
+
+void test_network_remotes__check_structure_version(void)
+{
+ git_transport transport = GIT_TRANSPORT_INIT;
+ const git_error *err;
+
+ git_remote_free(_remote);
+ cl_git_pass(git_remote_new(&_remote, _repo, NULL, "test-protocol://localhost", NULL));
+
+ transport.version = 0;
+ cl_git_fail(git_remote_set_transport(_remote, &transport));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+
+ giterr_clear();
+ transport.version = 1024;
+ cl_git_fail(git_remote_set_transport(_remote, &transport));
+ err = giterr_last();
+ cl_assert_equal_i(GITERR_INVALID, err->klass);
+}
diff --git a/tests-clar/object/peel.c b/tests-clar/object/peel.c
index a19772858..bb0bbd096 100644
--- a/tests-clar/object/peel.c
+++ b/tests-clar/object/peel.c
@@ -79,12 +79,12 @@ void test_object_peel__can_peel_a_commit(void)
void test_object_peel__cannot_peel_a_tree(void)
{
- assert_peel_error(GIT_ERROR, "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_BLOB);
+ assert_peel_error(GIT_EAMBIGUOUS, "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_BLOB);
}
void test_object_peel__cannot_peel_a_blob(void)
{
- assert_peel_error(GIT_ERROR, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_COMMIT);
+ assert_peel_error(GIT_ENOTFOUND, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_COMMIT);
}
void test_object_peel__target_any_object_for_type_change(void)
@@ -98,8 +98,13 @@ void test_object_peel__target_any_object_for_type_change(void)
"53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE);
/* fail to peel tree */
- assert_peel_error(GIT_ERROR, "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_ANY);
+ assert_peel_error(GIT_EAMBIGUOUS, "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_ANY);
/* fail to peel blob */
- assert_peel_error(GIT_ERROR, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_ANY);
+ assert_peel_error(GIT_ENOTFOUND, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_ANY);
+}
+
+void test_object_peel__should_use_a_well_known_type(void)
+{
+ assert_peel_error(GIT_EINVALIDSPEC, "7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ__EXT2);
}
diff --git a/tests-clar/object/tag/write.c b/tests-clar/object/tag/write.c
index ad6ca76b2..eb0ac2897 100644
--- a/tests-clar/object/tag/write.c
+++ b/tests-clar/object/tag/write.c
@@ -88,7 +88,6 @@ void test_object_tag_write__overwrite(void)
git_object_free(target);
git_signature_free(tagger);
-
}
void test_object_tag_write__replace(void)
@@ -190,3 +189,33 @@ void test_object_tag_write__delete(void)
git_reference_free(ref_tag);
}
+
+void test_object_tag_write__creating_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ git_oid target_id, tag_id;
+ git_signature *tagger;
+ git_object *target;
+
+ git_oid_fromstr(&target_id, tagged_commit);
+ cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT));
+
+ cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60));
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_tag_create(&tag_id, g_repo,
+ "Inv@{id", target, tagger, tagger_message, 0)
+ );
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_tag_create_lightweight(&tag_id, g_repo,
+ "Inv@{id", target, 0)
+ );
+
+ git_object_free(target);
+ git_signature_free(tagger);
+}
+
+void test_object_tag_write__deleting_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_tag_delete(g_repo, "Inv@{id"));
+}
diff --git a/tests-clar/object/tree/attributes.c b/tests-clar/object/tree/attributes.c
index 054f67137..b5319d30e 100644
--- a/tests-clar/object/tree/attributes.c
+++ b/tests-clar/object/tree/attributes.c
@@ -34,14 +34,14 @@ void test_object_tree_attributes__group_writable_tree_entries_created_with_an_an
entry = git_tree_entry_byname(tree, "old_mode.txt");
cl_assert_equal_i(
- GIT_FILEMODE_BLOB_GROUP_WRITABLE,
+ GIT_FILEMODE_BLOB,
git_tree_entry_filemode(entry));
git_tree_free(tree);
git_repository_free(repo);
}
-void test_object_tree_attributes__normalize_attributes_when_inserting_in_a_new_tree(void)
+void test_object_tree_attributes__treebuilder_reject_invalid_filemode(void)
{
git_repository *repo;
git_treebuilder *builder;
@@ -55,28 +55,14 @@ void test_object_tree_attributes__normalize_attributes_when_inserting_in_a_new_t
cl_git_pass(git_treebuilder_create(&builder, NULL));
- cl_git_pass(git_treebuilder_insert(
+ cl_git_fail(git_treebuilder_insert(
&entry,
builder,
"normalized.txt",
&bid,
GIT_FILEMODE_BLOB_GROUP_WRITABLE));
- cl_assert_equal_i(
- GIT_FILEMODE_BLOB,
- git_tree_entry_filemode(entry));
-
- cl_git_pass(git_treebuilder_write(&tid, repo, builder));
git_treebuilder_free(builder);
-
- cl_git_pass(git_tree_lookup(&tree, repo, &tid));
-
- entry = git_tree_entry_byname(tree, "normalized.txt");
- cl_assert_equal_i(
- GIT_FILEMODE_BLOB,
- git_tree_entry_filemode(entry));
-
- git_tree_free(tree);
cl_git_sandbox_cleanup();
}
@@ -113,3 +99,22 @@ void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from
git_tree_free(tree);
cl_git_sandbox_cleanup();
}
+
+void test_object_tree_attributes__normalize_600(void)
+{
+ git_oid id;
+ git_tree *tree;
+ git_repository *repo;
+ const git_tree_entry *entry;
+
+ repo = cl_git_sandbox_init("deprecated-mode.git");
+
+ git_oid_fromstr(&id, "0810fb7818088ff5ac41ee49199b51473b1bd6c7");
+ cl_git_pass(git_tree_lookup(&tree, repo, &id));
+
+ entry = git_tree_entry_byname(tree, "ListaTeste.xml");
+ cl_assert_equal_i(entry->attr, GIT_FILEMODE_BLOB);
+
+ git_tree_free(tree);
+ cl_git_sandbox_cleanup();
+}
diff --git a/tests-clar/odb/sorting.c b/tests-clar/odb/sorting.c
index bf64f6af4..b4f9e44bc 100644
--- a/tests-clar/odb/sorting.c
+++ b/tests-clar/odb/sorting.c
@@ -11,11 +11,11 @@ static git_odb_backend *new_backend(int position)
{
fake_backend *b;
- b = git__malloc(sizeof(fake_backend));
+ b = git__calloc(1, sizeof(fake_backend));
if (b == NULL)
return NULL;
- memset(b, 0x0, sizeof(fake_backend));
+ b->base.version = GIT_ODB_BACKEND_VERSION;
b->position = position;
return (git_odb_backend *)b;
}
diff --git a/tests-clar/refs/branches/create.c b/tests-clar/refs/branches/create.c
index a8c4d4f51..693a592a3 100644
--- a/tests-clar/refs/branches/create.c
+++ b/tests-clar/refs/branches/create.c
@@ -65,3 +65,12 @@ void test_refs_branches_create__can_force_create_over_an_existing_branch(void)
cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target)));
cl_assert_equal_s("refs/heads/br2", git_reference_name(branch));
}
+
+
+void test_refs_branches_create__creating_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ retrieve_known_commit(&target, repo);
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_branch_create(&branch, repo, "inv@{id", target, 0));
+} \ No newline at end of file
diff --git a/tests-clar/refs/branches/lookup.c b/tests-clar/refs/branches/lookup.c
index d07ed0ed8..95d49a4b3 100644
--- a/tests-clar/refs/branches/lookup.c
+++ b/tests-clar/refs/branches/lookup.c
@@ -35,3 +35,11 @@ void test_refs_branches_lookup__trying_to_retrieve_an_unknown_branch_returns_ENO
cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "where/are/you", GIT_BRANCH_LOCAL));
cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "over/here", GIT_BRANCH_REMOTE));
}
+
+void test_refs_branches_lookup__trying_to_retrieve_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_branch_lookup(&branch, repo, "are/you/inv@{id", GIT_BRANCH_LOCAL));
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_branch_lookup(&branch, repo, "yes/i am", GIT_BRANCH_REMOTE));
+}
diff --git a/tests-clar/refs/branches/move.c b/tests-clar/refs/branches/move.c
index 4bf1d69d0..17fb6dfe6 100644
--- a/tests-clar/refs/branches/move.c
+++ b/tests-clar/refs/branches/move.c
@@ -51,6 +51,11 @@ void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_coll
cl_assert_equal_i(GIT_EEXISTS, git_branch_move(ref, "master", 0));
}
+void test_refs_branches_move__moving_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_branch_move(ref, "Inv@{id", 0));
+}
+
void test_refs_branches_move__can_not_move_a_non_branch(void)
{
git_reference *tag;
diff --git a/tests-clar/refs/branches/tracking.c b/tests-clar/refs/branches/tracking.c
index e8b2f24d7..bc41e0633 100644
--- a/tests-clar/refs/branches/tracking.c
+++ b/tests-clar/refs/branches/tracking.c
@@ -61,11 +61,12 @@ void test_refs_branches_tracking__trying_to_retrieve_a_remote_tracking_reference
cl_assert_equal_i(GIT_ENOTFOUND, git_branch_tracking(&tracking, branch));
}
-static void assert_merge_and_or_remote_key_missing(git_repository *repository, git_object *target, const char *entry_name)
+static void assert_merge_and_or_remote_key_missing(git_repository *repository, const git_commit *target, const char *entry_name)
{
git_reference *branch;
- cl_git_pass(git_branch_create(&branch, repository, entry_name, target, 0));
+ cl_assert_equal_i(GIT_OBJ_COMMIT, git_object_type(target));
+ cl_git_pass(git_branch_create(&branch, repository, entry_name, (git_commit*)target, 0));
cl_assert_equal_i(GIT_ENOTFOUND, git_branch_tracking(&tracking, branch));
@@ -76,19 +77,19 @@ void test_refs_branches_tracking__retrieve_a_remote_tracking_reference_from_a_br
{
git_reference *head;
git_repository *repository;
- git_object *target;
+ git_commit *target;
repository = cl_git_sandbox_init("testrepo.git");
cl_git_pass(git_repository_head(&head, repository));
- cl_git_pass(git_reference_peel(&target, head, GIT_OBJ_COMMIT));
+ cl_git_pass(git_reference_peel(((git_object **)&target), head, GIT_OBJ_COMMIT));
git_reference_free(head);
assert_merge_and_or_remote_key_missing(repository, target, "remoteless");
assert_merge_and_or_remote_key_missing(repository, target, "mergeless");
assert_merge_and_or_remote_key_missing(repository, target, "mergeandremoteless");
- git_object_free(target);
+ git_commit_free(target);
cl_git_sandbox_cleanup();
}
diff --git a/tests-clar/refs/create.c b/tests-clar/refs/create.c
index bef9bfd24..56c323d8a 100644
--- a/tests-clar/refs/create.c
+++ b/tests-clar/refs/create.c
@@ -25,16 +25,11 @@ void test_refs_create__symbolic(void)
git_reference *new_reference, *looked_up_ref, *resolved_ref;
git_repository *repo2;
git_oid id;
- git_buf ref_path = GIT_BUF_INIT;
const char *new_head_tracker = "ANOTHER_HEAD_TRACKER";
git_oid_fromstr(&id, current_master_tip);
- /* Retrieve the physical path to the symbolic ref for further cleaning */
- cl_git_pass(git_buf_joinpath(&ref_path, g_repo->path_repository, new_head_tracker));
- git_buf_free(&ref_path);
-
/* Create and write the new symbolic reference */
cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0));
@@ -72,13 +67,11 @@ void test_refs_create__deep_symbolic(void)
// create a deep symbolic reference
git_reference *new_reference, *looked_up_ref, *resolved_ref;
git_oid id;
- git_buf ref_path = GIT_BUF_INIT;
const char *new_head_tracker = "deep/rooted/tracker";
git_oid_fromstr(&id, current_master_tip);
- cl_git_pass(git_buf_joinpath(&ref_path, g_repo->path_repository, new_head_tracker));
cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0));
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker));
cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
@@ -87,7 +80,6 @@ void test_refs_create__deep_symbolic(void)
git_reference_free(new_reference);
git_reference_free(looked_up_ref);
git_reference_free(resolved_ref);
- git_buf_free(&ref_path);
}
void test_refs_create__oid(void)
@@ -96,15 +88,11 @@ void test_refs_create__oid(void)
git_reference *new_reference, *looked_up_ref;
git_repository *repo2;
git_oid id;
- git_buf ref_path = GIT_BUF_INIT;
const char *new_head = "refs/heads/new-head";
git_oid_fromstr(&id, current_master_tip);
- /* Retrieve the physical path to the symbolic ref for further cleaning */
- cl_git_pass(git_buf_joinpath(&ref_path, g_repo->path_repository, new_head));
-
/* Create and write the new object id reference */
cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0));
@@ -128,7 +116,6 @@ void test_refs_create__oid(void)
git_reference_free(new_reference);
git_reference_free(looked_up_ref);
- git_buf_free(&ref_path);
}
void test_refs_create__oid_unknown(void)
@@ -162,3 +149,19 @@ void test_refs_create__propagate_eexists(void)
error = git_reference_symbolic_create(&ref, g_repo, "HEAD", current_head_target, false);
cl_assert(error == GIT_EEXISTS);
}
+
+void test_refs_create__creating_a_reference_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ git_reference *new_reference;
+ git_oid id;
+
+ const char *name = "refs/heads/inv@{id";
+
+ git_oid_fromstr(&id, current_master_tip);
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_create(
+ &new_reference, g_repo, name, &id, 0));
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create(
+ &new_reference, g_repo, name, current_head_target, 0));
+}
diff --git a/tests-clar/refs/normalize.c b/tests-clar/refs/normalize.c
index a144ef5c0..870a533ca 100644
--- a/tests-clar/refs/normalize.c
+++ b/tests-clar/refs/normalize.c
@@ -21,7 +21,9 @@ static void ensure_refname_invalid(unsigned int flags, const char *input_refname
{
char buffer_out[GIT_REFNAME_MAX];
- cl_git_fail(git_reference_normalize_name(buffer_out, sizeof(buffer_out), input_refname, flags));
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC,
+ git_reference_normalize_name(buffer_out, sizeof(buffer_out), input_refname, flags));
}
void test_refs_normalize__can_normalize_a_direct_reference_name(void)
diff --git a/tests-clar/refs/peel.c b/tests-clar/refs/peel.c
index 6fa6009d5..34bd02ce0 100644
--- a/tests-clar/refs/peel.c
+++ b/tests-clar/refs/peel.c
@@ -78,7 +78,7 @@ void test_refs_peel__can_peel_a_symbolic_reference(void)
void test_refs_peel__cannot_peel_into_a_non_existing_target(void)
{
- assert_peel_error(GIT_ERROR, "refs/tags/point_to_blob", GIT_OBJ_TAG);
+ assert_peel_error(GIT_ENOTFOUND, "refs/tags/point_to_blob", GIT_OBJ_TAG);
}
void test_refs_peel__can_peel_into_any_non_tag_object(void)
diff --git a/tests-clar/refs/read.c b/tests-clar/refs/read.c
index c10a540c0..3e2a59afd 100644
--- a/tests-clar/refs/read.c
+++ b/tests-clar/refs/read.c
@@ -223,11 +223,19 @@ void test_refs_read__trailing(void)
void test_refs_read__unfound_return_ENOTFOUND(void)
{
git_reference *reference;
+ git_oid id;
- cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "TEST_MASTER"));
- cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/test/master"));
- cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/master"));
- cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&reference, g_repo, "refs/tags/test/farther/master"));
+ cl_assert_equal_i(GIT_ENOTFOUND,
+ git_reference_lookup(&reference, g_repo, "TEST_MASTER"));
+ cl_assert_equal_i(GIT_ENOTFOUND,
+ git_reference_lookup(&reference, g_repo, "refs/test/master"));
+ cl_assert_equal_i(GIT_ENOTFOUND,
+ git_reference_lookup(&reference, g_repo, "refs/tags/test/master"));
+ cl_assert_equal_i(GIT_ENOTFOUND,
+ git_reference_lookup(&reference, g_repo, "refs/tags/test/farther/master"));
+
+ cl_assert_equal_i(GIT_ENOTFOUND,
+ git_reference_name_to_id(&id, g_repo, "refs/tags/test/farther/master"));
}
static void assert_is_branch(const char *name, bool expected_branchness)
@@ -245,3 +253,15 @@ void test_refs_read__can_determine_if_a_reference_is_a_local_branch(void)
assert_is_branch("refs/remotes/test/master", false);
assert_is_branch("refs/tags/e90810b", false);
}
+
+void test_refs_read__invalid_name_returns_EINVALIDSPEC(void)
+{
+ git_reference *reference;
+ git_oid id;
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_reference_lookup(&reference, g_repo, "refs/heads/Inv@{id"));
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_reference_name_to_id(&id, g_repo, "refs/heads/Inv@{id"));
+}
diff --git a/tests-clar/refs/reflog/reflog.c b/tests-clar/refs/reflog/reflog.c
index 8743c8a76..19ee53567 100644
--- a/tests-clar/refs/reflog/reflog.c
+++ b/tests-clar/refs/reflog/reflog.c
@@ -170,3 +170,15 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void)
git_buf_free(&moved_log_path);
git_buf_free(&master_log_path);
}
+
+void test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ git_reference *master;
+
+ cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master"));
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC,
+ git_reflog_rename(master, "refs/heads/Inv@{id"));
+
+ git_reference_free(master);
+}
diff --git a/tests-clar/refs/rename.c b/tests-clar/refs/rename.c
index ec5c12507..bfdef15fa 100644
--- a/tests-clar/refs/rename.c
+++ b/tests-clar/refs/rename.c
@@ -180,10 +180,14 @@ void test_refs_rename__invalid_name(void)
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
/* Can not be renamed with an invalid name. */
- cl_git_fail(git_reference_rename(looked_up_ref, "Hello! I'm a very invalid name.", 0));
-
- /* Can not be renamed outside of the refs hierarchy. */
- cl_git_fail(git_reference_rename(looked_up_ref, "i-will-sudo-you", 0));
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC,
+ git_reference_rename(looked_up_ref, "Hello! I'm a very invalid name.", 0));
+
+ /* Can not be renamed outside of the refs hierarchy
+ * unless it's ALL_CAPS_AND_UNDERSCORES.
+ */
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_rename(looked_up_ref, "i-will-sudo-you", 0));
/* Failure to rename it hasn't corrupted its state */
git_reference_free(looked_up_ref);
diff --git a/tests-clar/refs/revparse.c b/tests-clar/refs/revparse.c
index 3698b5197..81a6bc469 100644
--- a/tests-clar/refs/revparse.c
+++ b/tests-clar/refs/revparse.c
@@ -7,9 +7,6 @@
static git_repository *g_repo;
static git_object *g_obj;
-static char g_orig_tz[16] = {0};
-
-
/* Helpers */
static void test_object_inrepo(const char *spec, const char *expected_oid, git_repository *repo)
@@ -37,19 +34,12 @@ static void test_object(const char *spec, const char *expected_oid)
void test_refs_revparse__initialize(void)
{
- char *tz = cl_getenv("TZ");
- if (tz)
- strcpy(g_orig_tz, tz);
- cl_setenv("TZ", "UTC");
-
cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
}
void test_refs_revparse__cleanup(void)
{
git_repository_free(g_repo);
- g_obj = NULL;
- cl_setenv("TZ", g_orig_tz);
}
void test_refs_revparse__nonexistant_object(void)
@@ -59,13 +49,17 @@ void test_refs_revparse__nonexistant_object(void)
test_object("this-does-not-exist~2", NULL);
}
-void test_refs_revparse__invalid_reference_name(void)
+static void assert_invalid_spec(const char *invalid_spec)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't make sense"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't make sense^1"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't make sense~2"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, ""));
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC, git_revparse_single(&g_obj, g_repo, invalid_spec));
+}
+void test_refs_revparse__invalid_reference_name(void)
+{
+ assert_invalid_spec("this doesn't make sense");
+ assert_invalid_spec("Inv@{id");
+ assert_invalid_spec("");
}
void test_refs_revparse__shas(void)
@@ -104,9 +98,11 @@ void test_refs_revparse__describe_output(void)
void test_refs_revparse__nth_parent(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "be3563a^-1"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "^"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "be3563a^{tree}^"));
+ assert_invalid_spec("be3563a^-1");
+ assert_invalid_spec("^");
+ assert_invalid_spec("be3563a^{tree}^");
+ assert_invalid_spec("point_to_blob^{blob}^");
+ assert_invalid_spec("this doesn't make sense^1");
test_object("be3563a^1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
test_object("be3563a^", "9fd738e8f7967c078dceed8190330fc8648ee56a");
@@ -133,8 +129,10 @@ void test_refs_revparse__not_tag(void)
void test_refs_revparse__to_type(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "wrapped_tag^{blob}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "wrapped_tag^{trip}"));
+ assert_invalid_spec("wrapped_tag^{trip}");
+ test_object("point_to_blob^{commit}", NULL);
+ cl_assert_equal_i(
+ GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "wrapped_tag^{blob}"));
test_object("wrapped_tag^{commit}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("wrapped_tag^{tree}", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162");
@@ -144,11 +142,15 @@ void test_refs_revparse__to_type(void)
void test_refs_revparse__linear_history(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "~"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "foo~bar"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "master~bar"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "master~-1"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "master~0bar"));
+ assert_invalid_spec("~");
+ test_object("foo~bar", NULL);
+
+ assert_invalid_spec("master~bar");
+ assert_invalid_spec("master~-1");
+ assert_invalid_spec("master~0bar");
+ assert_invalid_spec("this doesn't make sense~2");
+ assert_invalid_spec("be3563a^{tree}~");
+ assert_invalid_spec("point_to_blob^{blob}~");
test_object("master~0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("master~1", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
@@ -159,10 +161,10 @@ void test_refs_revparse__linear_history(void)
void test_refs_revparse__chaining(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "master@{0}@{0}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{u}@{-1}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-1}@{-1}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-3}@{0}"));
+ assert_invalid_spec("master@{0}@{0}");
+ assert_invalid_spec("@{u}@{-1}");
+ assert_invalid_spec("@{-1}@{-1}");
+ assert_invalid_spec("@{-3}@{0}");
test_object("master@{0}~1^1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
test_object("@{u}@{0}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
@@ -178,8 +180,9 @@ void test_refs_revparse__chaining(void)
void test_refs_revparse__upstream(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "e90810b@{u}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "refs/tags/e90810b@{u}"));
+ assert_invalid_spec("e90810b@{u}");
+ assert_invalid_spec("refs/tags/e90810b@{u}");
+ test_object("refs/heads/e90810b@{u}", NULL);
test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
@@ -190,7 +193,7 @@ void test_refs_revparse__upstream(void)
void test_refs_revparse__ordinal(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "master@{-2}"));
+ assert_invalid_spec("master@{-2}");
/* TODO: make the test below actually fail
* cl_git_fail(git_revparse_single(&g_obj, g_repo, "master@{1a}"));
@@ -212,9 +215,9 @@ void test_refs_revparse__ordinal(void)
void test_refs_revparse__previous_head(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-xyz}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-0}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "@{-1b}"));
+ assert_invalid_spec("@{-xyz}");
+ assert_invalid_spec("@{-0}");
+ assert_invalid_spec("@{-1b}");
test_object("@{-42}", NULL);
@@ -271,9 +274,9 @@ void test_refs_revparse__reflog_of_a_ref_under_refs(void)
void test_refs_revparse__revwalk(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/not found in any commit}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/merge}"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, "master^{/((}"));
+ test_object("master^{/not found in any commit}", NULL);
+ test_object("master^{/merge}", NULL);
+ assert_invalid_spec("master^{/((}");
test_object("master^{/anoth}", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
test_object("master^{/Merge}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
@@ -354,8 +357,9 @@ void test_refs_revparse__date(void)
void test_refs_revparse__colon(void)
{
- cl_git_fail(git_revparse_single(&g_obj, g_repo, ":/"));
- cl_git_fail(git_revparse_single(&g_obj, g_repo, ":2:README"));
+ assert_invalid_spec(":/");
+ assert_invalid_spec("point_to_blob:readme.txt");
+ cl_git_fail(git_revparse_single(&g_obj, g_repo, ":2:README")); /* Not implemented */
test_object(":/not found in any commit", NULL);
test_object("subtrees:ab/42.txt", NULL);
@@ -445,11 +449,8 @@ void test_refs_revparse__disambiguation(void)
void test_refs_revparse__a_too_short_objectid_returns_EAMBIGUOUS(void)
{
- int result;
-
- result = git_revparse_single(&g_obj, g_repo, "e90");
-
- cl_assert_equal_i(GIT_EAMBIGUOUS, result);
+ cl_assert_equal_i(
+ GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "e90"));
}
void test_refs_revparse__issue_994(void)
diff --git a/tests-clar/refs/update.c b/tests-clar/refs/update.c
new file mode 100644
index 000000000..6c2107ee2
--- /dev/null
+++ b/tests-clar/refs/update.c
@@ -0,0 +1,29 @@
+#include "clar_libgit2.h"
+
+#include "refs.h"
+
+static git_repository *g_repo;
+
+void test_refs_update__initialize(void)
+{
+ g_repo = cl_git_sandbox_init("testrepo.git");
+}
+
+void test_refs_update__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+void test_refs_update__updating_the_target_of_a_symref_with_an_invalid_name_returns_EINVALIDSPEC(void)
+{
+ git_reference *head;
+
+ cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE));
+
+ cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head));
+
+ cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_set_target(
+ head, "refs/heads/inv@{id"));
+
+ git_reference_free(head);
+}
diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c
index 3b14c97f2..c0acbed5a 100644
--- a/tests-clar/repo/init.c
+++ b/tests-clar/repo/init.c
@@ -304,8 +304,7 @@ void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void)
void test_repo_init__extended_0(void)
{
- git_repository_init_options opts;
- memset(&opts, 0, sizeof(opts));
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
/* without MKDIR this should fail */
cl_git_fail(git_repository_init_ext(&_repo, "extended", &opts));
@@ -327,8 +326,7 @@ void test_repo_init__extended_1(void)
git_reference *ref;
git_remote *remote;
struct stat st;
- git_repository_init_options opts;
- memset(&opts, 0, sizeof(opts));
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
opts.flags = GIT_REPOSITORY_INIT_MKPATH |
GIT_REPOSITORY_INIT_NO_DOTGIT_DIR;
@@ -367,8 +365,7 @@ void test_repo_init__extended_1(void)
void test_repo_init__extended_with_template(void)
{
- git_repository_init_options opts;
- memset(&opts, 0, sizeof(opts));
+ git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE;
opts.template_path = cl_fixture("template");
diff --git a/tests-clar/resources/deprecated-mode.git/objects/08/10fb7818088ff5ac41ee49199b51473b1bd6c7 b/tests-clar/resources/deprecated-mode.git/objects/08/10fb7818088ff5ac41ee49199b51473b1bd6c7
new file mode 100644
index 000000000..52d56936a
--- /dev/null
+++ b/tests-clar/resources/deprecated-mode.git/objects/08/10fb7818088ff5ac41ee49199b51473b1bd6c7
Binary files differ
diff --git a/tests-clar/status/ignore.c b/tests-clar/status/ignore.c
index 27f9d85b9..e2e4aaf18 100644
--- a/tests-clar/status/ignore.c
+++ b/tests-clar/status/ignore.c
@@ -180,9 +180,6 @@ void test_status_ignore__subdirectories(void)
{
status_entry_single st;
int ignored;
- git_status_options opts;
-
- GIT_UNUSED(opts);
g_repo = cl_git_sandbox_init("empty_standard_repo");
@@ -216,11 +213,6 @@ void test_status_ignore__subdirectories(void)
cl_git_mkfile(
"empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!");
- opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
- opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED |
- GIT_STATUS_OPT_INCLUDE_UNTRACKED |
- GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
-
memset(&st, 0, sizeof(st));
cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st));
cl_assert_equal_i(2, st.count);
diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c
index 838a04377..a1f7f8684 100644
--- a/tests-clar/status/worktree.c
+++ b/tests-clar/status/worktree.c
@@ -111,7 +111,7 @@ void test_status_worktree__swap_subdir_and_file(void)
status_entry_counts counts;
git_repository *repo = cl_git_sandbox_init("status");
git_index *index;
- git_status_options opts;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
bool ignore_case;
cl_git_pass(git_repository_index(&index, repo));
@@ -133,7 +133,6 @@ void test_status_worktree__swap_subdir_and_file(void)
counts.expected_paths = ignore_case ? entry_paths3_icase : entry_paths3;
counts.expected_statuses = ignore_case ? entry_statuses3_icase : entry_statuses3;
- memset(&opts, 0, sizeof(opts));
opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
GIT_STATUS_OPT_INCLUDE_IGNORED;
@@ -150,7 +149,7 @@ void test_status_worktree__swap_subdir_with_recurse_and_pathspec(void)
{
status_entry_counts counts;
git_repository *repo = cl_git_sandbox_init("status");
- git_status_options opts;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
/* first alter the contents of the worktree */
cl_git_pass(p_rename("status/current_file", "status/swap"));
@@ -167,7 +166,6 @@ void test_status_worktree__swap_subdir_with_recurse_and_pathspec(void)
counts.expected_paths = entry_paths4;
counts.expected_statuses = entry_statuses4;
- memset(&opts, 0, sizeof(opts));
opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
/* TODO: set pathspec to "current_file" eventually */
@@ -691,7 +689,7 @@ void test_status_worktree__filemode_changes(void)
{
git_repository *repo = cl_git_sandbox_init("filemodes");
status_entry_counts counts;
- git_status_options opts;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
git_config *cfg;
/* overwrite stored filemode with platform appropriate value */
@@ -708,7 +706,6 @@ void test_status_worktree__filemode_changes(void)
filemode_statuses[i] = GIT_STATUS_CURRENT;
}
- memset(&opts, 0, sizeof(opts));
opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
GIT_STATUS_OPT_INCLUDE_IGNORED |
GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
@@ -746,7 +743,7 @@ static int cb_status__expected_path(const char *p, unsigned int s, void *payload
void test_status_worktree__disable_pathspec_match(void)
{
git_repository *repo;
- git_status_options opts;
+ git_status_options opts = GIT_STATUS_OPTIONS_INIT;
char *file_with_bracket = "LICENSE[1].md",
*imaginary_file_with_bracket = "LICENSE[1-2].md";
@@ -754,7 +751,6 @@ void test_status_worktree__disable_pathspec_match(void)
cl_git_mkfile("pathspec/LICENSE[1].md", "screaming bracket\n");
cl_git_mkfile("pathspec/LICENSE1.md", "no bracket\n");
- memset(&opts, 0, sizeof(opts));
opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH;
opts.pathspec.count = 1;
@@ -843,3 +839,79 @@ void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void
cl_assert_equal_i(GIT_STATUS_CURRENT, status);
}
+
+void test_status_worktree__conflicted_item(void)
+{
+ git_repository *repo = cl_git_sandbox_init("status");
+ git_index *index;
+ unsigned int status;
+ git_index_entry ancestor_entry, our_entry, their_entry;
+
+ memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
+ memset(&our_entry, 0x0, sizeof(git_index_entry));
+ memset(&their_entry, 0x0, sizeof(git_index_entry));
+
+ ancestor_entry.path = "modified_file";
+ git_oid_fromstr(&ancestor_entry.oid,
+ "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
+
+ our_entry.path = "modified_file";
+ git_oid_fromstr(&our_entry.oid,
+ "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
+
+ their_entry.path = "modified_file";
+ git_oid_fromstr(&their_entry.oid,
+ "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
+
+ cl_git_pass(git_status_file(&status, repo, "modified_file"));
+ cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status);
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_git_pass(git_index_conflict_add(index, &ancestor_entry,
+ &our_entry, &their_entry));
+
+ cl_git_pass(git_status_file(&status, repo, "modified_file"));
+ cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status);
+
+ git_index_free(index);
+}
+
+void test_status_worktree__conflict_with_diff3(void)
+{
+ git_repository *repo = cl_git_sandbox_init("status");
+ git_index *index;
+ unsigned int status;
+ git_index_entry ancestor_entry, our_entry, their_entry;
+
+ memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
+ memset(&our_entry, 0x0, sizeof(git_index_entry));
+ memset(&their_entry, 0x0, sizeof(git_index_entry));
+
+ ancestor_entry.path = "modified_file";
+ git_oid_fromstr(&ancestor_entry.oid,
+ "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
+
+ our_entry.path = "modified_file";
+ git_oid_fromstr(&our_entry.oid,
+ "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
+
+ their_entry.path = "modified_file";
+ git_oid_fromstr(&their_entry.oid,
+ "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
+
+ cl_git_pass(git_status_file(&status, repo, "modified_file"));
+ cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status);
+
+ cl_git_pass(git_repository_index(&index, repo));
+
+ cl_git_pass(git_index_remove(index, "modified_file", 0));
+ cl_git_pass(git_index_conflict_add(index, &ancestor_entry,
+ &our_entry, &their_entry));
+
+ cl_git_pass(git_status_file(&status, repo, "modified_file"));
+
+ cl_assert_equal_i(GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, status);
+
+ git_index_free(index);
+}
+