Commit a21bb1aa by Chris Young

Merge remote-tracking branch 'source/development' into development

parents 96ef3d84 86ea6ced
......@@ -6,6 +6,7 @@ Alexei Sholik
Andreas Ericsson
Ankur Sethi
Ben Noordhuis
Ben Straub
Benjamin C Meyer
Brian Lopez
Carlos Martín Nieto
......
......@@ -155,6 +155,12 @@ SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_VERSION_MAJOR})
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libgit2.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libgit2.pc @ONLY)
IF (MSVC)
# Precompiled headers
SET_TARGET_PROPERTIES(git2 PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
SET_SOURCE_FILES_PROPERTIES(src/win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
ENDIF ()
# Install
INSTALL(TARGETS git2
RUNTIME DESTINATION ${INSTALL_BIN}
......@@ -187,6 +193,12 @@ IF (BUILD_CLAR)
)
ADD_EXECUTABLE(libgit2_clar ${SRC} ${CLAR_PATH}/clar_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX})
TARGET_LINK_LIBRARIES(libgit2_clar ${CMAKE_THREAD_LIBS_INIT} ${SSL_LIBRARIES})
IF (MSVC)
# Precompiled headers
SET_TARGET_PROPERTIES(libgit2_clar PROPERTIES COMPILE_FLAGS "/Yuprecompiled.h /FIprecompiled.h")
ENDIF ()
IF (WIN32)
TARGET_LINK_LIBRARIES(libgit2_clar ws2_32)
ELSEIF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
......
......@@ -185,9 +185,7 @@ int main(int argc, char *argv[])
/* open repo */
check(git_repository_discover(path, sizeof(path), dir, 0, "/"),
"Could not discover repository");
check(git_repository_open(&repo, path),
check(git_repository_open_ext(&repo, dir, 0, NULL),
"Could not open repository");
if (treeish1)
......
......@@ -25,6 +25,7 @@
#include "git2/merge.h"
#include "git2/refs.h"
#include "git2/reflog.h"
#include "git2/revparse.h"
#include "git2/object.h"
#include "git2/blob.h"
......@@ -43,5 +44,6 @@
#include "git2/indexer.h"
#include "git2/submodule.h"
#include "git2/notes.h"
#include "git2/reset.h"
#endif
......@@ -29,6 +29,10 @@
*/
GIT_BEGIN_DECL
/**
* Flags for diff options. A combination of these flags can be passed
* in via the `flags` value in the `git_diff_options`.
*/
enum {
GIT_DIFF_NORMAL = 0,
GIT_DIFF_REVERSE = (1 << 0),
......@@ -96,9 +100,9 @@ typedef enum {
typedef struct {
git_oid oid;
char *path;
uint16_t mode;
git_off_t size;
unsigned int flags;
uint16_t mode;
} git_diff_file;
/**
......@@ -160,15 +164,16 @@ typedef int (*git_diff_hunk_fn)(
* the file or hunk headers.
*/
enum {
/* these values will be sent to `git_diff_data_fn` along with the line */
/* These values will be sent to `git_diff_data_fn` along with the line */
GIT_DIFF_LINE_CONTEXT = ' ',
GIT_DIFF_LINE_ADDITION = '+',
GIT_DIFF_LINE_DELETION = '-',
GIT_DIFF_LINE_ADD_EOFNL = '\n', /**< LF was added at end of file */
GIT_DIFF_LINE_ADD_EOFNL = '\n', /**< DEPRECATED */
GIT_DIFF_LINE_DEL_EOFNL = '\0', /**< LF was removed at end of file */
/* these values will only be sent to a `git_diff_data_fn` when the content
* of a diff is being formatted (eg. through git_diff_print_patch() or
* git_diff_print_compact(), for instance).
/* The following values will only be sent to a `git_diff_data_fn` when
* the content of a diff is being formatted (eg. through
* git_diff_print_patch() or git_diff_print_compact(), for instance).
*/
GIT_DIFF_LINE_FILE_HDR = 'F',
GIT_DIFF_LINE_HUNK_HDR = 'H',
......@@ -206,6 +211,8 @@ GIT_EXTERN(void) git_diff_list_free(git_diff_list *diff);
/**
* Compute a difference between two tree objects.
*
* This is equivalent to `git diff <treeish> <treeish>`
*
* @param repo The repository containing the trees.
* @param opts Structure with options to influence diff or NULL for defaults.
* @param old_tree A git_tree object to diff from.
......@@ -222,6 +229,9 @@ GIT_EXTERN(int) git_diff_tree_to_tree(
/**
* Compute a difference between a tree and the index.
*
* This is equivalent to `git diff --cached <treeish>` or if you pass
* the HEAD tree, then like `git diff --cached`.
*
* @param repo The repository containing the tree and index.
* @param opts Structure with options to influence diff or NULL for defaults.
* @param old_tree A git_tree object to diff from.
......@@ -236,6 +246,11 @@ GIT_EXTERN(int) git_diff_index_to_tree(
/**
* Compute a difference between the working directory and the index.
*
* This matches the `git diff` command. See the note below on
* `git_diff_workdir_to_tree` for a discussion of the difference between
* `git diff` and `git diff HEAD` and how to emulate a `git diff <treeish>`
* using libgit2.
*
* @param repo The repository.
* @param opts Structure with options to influence diff or NULL for defaults.
* @param diff A pointer to a git_diff_list pointer that will be allocated.
......@@ -248,14 +263,24 @@ GIT_EXTERN(int) git_diff_workdir_to_index(
/**
* Compute a difference between the working directory and a tree.
*
* This returns strictly the differences between the tree and the
* files contained in the working directory, regardless of the state
* of files in the index. There is no direct equivalent in C git.
* This is *NOT* the same as `git diff <treeish>`. Running `git diff HEAD`
* or the like actually uses information from the index, along with the tree
* and workdir dir info.
*
* This function returns strictly the differences between the tree and the
* files contained in the working directory, regardless of the state of
* files in the index. It may come as a surprise, but there is no direct
* equivalent in core git.
*
* To emulate `git diff <treeish>`, you should call both
* `git_diff_index_to_tree` and `git_diff_workdir_to_index`, then call
* `git_diff_merge` on the results. That will yield a `git_diff_list` that
* matches the git output.
*
* This is *NOT* the same as 'git diff HEAD' or 'git diff <SHA>'. Those
* commands diff the tree, the index, and the workdir. To emulate those
* functions, call `git_diff_index_to_tree` and `git_diff_workdir_to_index`,
* then call `git_diff_merge` on the results.
* If this seems confusing, take the case of a file with a staged deletion
* where the file has then been put back into the working dir and modified.
* The tree-to-workdir diff for that file is 'modified', but core git would
* show status 'deleted' since there is a pending deletion in the index.
*
* @param repo The repository containing the tree.
* @param opts Structure with options to influence diff or NULL for defaults.
......@@ -298,10 +323,23 @@ GIT_EXTERN(int) git_diff_merge(
/**
* Iterate over a diff list issuing callbacks.
*
* If the hunk and/or line callbacks are not NULL, then this will calculate
* text diffs for all files it thinks are not binary. If those are both
* NULL, then this will not bother with the text diffs, so it can be
* efficient.
* This will iterate through all of the files described in a diff. You
* should provide a file callback to learn about each file.
*
* The "hunk" and "line" callbacks are optional, and the text diff of the
* files will only be calculated if they are not NULL. Of course, these
* callbacks will not be invoked for binary files on the diff list or for
* files whose only changed is a file mode change.
*
* @param diff A git_diff_list generated by one of the above functions.
* @param cb_data Reference pointer that will be passed to your callbacks.
* @param file_cb Callback function to make per file in the diff.
* @param hunk_cb Optional callback to make per hunk of text diff. This
* callback is called to describe a range of lines in the
* diff. It will not be issued for binary files.
* @param line_cb Optional callback to make per line of diff text. This
* same callback will be made for context lines, added, and
* removed lines, and even for a deleted trailing newline.
*/
GIT_EXTERN(int) git_diff_foreach(
git_diff_list *diff,
......@@ -322,6 +360,14 @@ GIT_EXTERN(int) git_diff_print_compact(
* Iterate over a diff generating text output like "git diff".
*
* This is a super easy way to generate a patch from a diff.
*
* @param diff A git_diff_list generated by one of the above functions.
* @param cb_data Reference pointer that will be passed to your callbacks.
* @param print_cb Callback function to output lines of the diff. This
* same function will be called for file headers, hunk
* headers, and diff lines. Fortunately, you can probably
* use various GIT_DIFF_LINE constants to determine what
* text you are given.
*/
GIT_EXTERN(int) git_diff_print_patch(
git_diff_list *diff,
......@@ -338,13 +384,14 @@ GIT_EXTERN(int) git_diff_print_patch(
/**
* Directly run a text diff on two blobs.
*
* Compared to a file, a blob lacks some contextual information. As such, the
* `git_diff_file` parameters of the callbacks will be filled accordingly to the following:
* `mode` will be set to 0, `path` will be set to NULL. When dealing with a NULL blob, `oid`
* will be set to 0.
* Compared to a file, a blob lacks some contextual information. As such,
* the `git_diff_file` parameters of the callbacks will be filled
* accordingly to the following: `mode` will be set to 0, `path` will be set
* to NULL. When dealing with a NULL blob, `oid` will be set to 0.
*
* When at least one of the blobs being dealt with is binary, the `git_diff_delta` binary
* attribute will be set to 1 and no call to the hunk_cb nor line_cb will be made.
* When at least one of the blobs being dealt with is binary, the
* `git_diff_delta` binary attribute will be set to 1 and no call to the
* hunk_cb nor line_cb will be made.
*/
GIT_EXTERN(int) git_diff_blobs(
git_blob *old_blob,
......
......@@ -20,6 +20,14 @@
GIT_BEGIN_DECL
/**
* Parse a refspec string and create a refspec object
*
* @param refspec pointer to the refspec structure to be used
* @param str the refspec as a string
*/
GIT_EXTERN(int) git_refspec_parse(git_refspec *refspec, const char *str);
/**
* Get the source specifier
*
* @param refspec the refspec
......
/*
* Copyright (C) 2009-2012 the libgit2 contributors
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_reset_h__
#define INCLUDE_git_reset_h__
/**
* @file git2/reset.h
* @brief Git reset management routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Sets the current head to the specified commit oid and optionally
* resets the index and working tree to match.
*
* When specifying a Soft kind of reset, the head will be moved to the commit.
*
* Specifying a Mixed kind of reset will trigger a Soft reset and the index will
* be replaced with the content of the commit tree.
*
* TODO: Implement remaining kinds of resets.
*
* @param repo Repository where to perform the reset operation.
*
* @param target Object to which the Head should be moved to. This object
* must belong to the given `repo` and can either be a git_commit or a
* git_tag. When a git_tag is being passed, it should be dereferencable
* to a git_commit which oid will be used as the target of the branch.
*
* @param reset_type Kind of reset operation to perform.
*
* @return GIT_SUCCESS or an error code
*/
GIT_EXTERN(int) git_reset(git_repository *repo, const git_object *target, git_reset_type reset_type);
/** @} */
GIT_END_DECL
#endif
/*
* Copyright (C) 2012 the libgit2 contributors
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_revparse_h__
#define INCLUDE_git_revparse_h__
#include "common.h"
#include "types.h"
/**
* @file git2/revparse.h
* @brief Git revision parsing routines
* @defgroup git_revparse Git revision parsing routines
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Find an object, as specified by a revision string. See `man gitrevisions`, or the documentation
* for `git rev-parse` for information on the syntax accepted.
*
* @param out pointer to output object
* @param repo the repository to search in
* @param spec the textual specification for an object
* @return on success, GIT_ERROR otherwise (use git_error_last for information about the error)
*/
GIT_EXTERN(int) git_revparse_single(git_object **out, git_repository *repo, const char *spec);
/** @} */
GIT_END_DECL
#endif
......@@ -102,7 +102,7 @@ enum {
GIT_STATUS_OPT_INCLUDE_UNTRACKED = (1 << 0),
GIT_STATUS_OPT_INCLUDE_IGNORED = (1 << 1),
GIT_STATUS_OPT_INCLUDE_UNMODIFIED = (1 << 2),
GIT_STATUS_OPT_EXCLUDE_SUBMODULED = (1 << 3),
GIT_STATUS_OPT_EXCLUDE_SUBMODULES = (1 << 3),
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = (1 << 4),
};
......
......@@ -169,6 +169,12 @@ typedef enum {
GIT_BRANCH_REMOTE = 2,
} git_branch_t;
/** Kinds of reset operation. */
typedef enum {
GIT_RESET_SOFT = 1,
GIT_RESET_MIXED = 2,
} git_reset_type;
typedef struct git_refspec git_refspec;
typedef struct git_remote git_remote;
......
......@@ -415,7 +415,7 @@ int git_attr_cache__push_file(
if (parse && (error = parse(repo, content, file)) < 0)
goto finish;
git_strmap_insert(cache->files, file->key, file, error);
git_strmap_insert(cache->files, file->key, file, error); //-V595
if (error > 0)
error = 0;
......
......@@ -149,9 +149,11 @@ static int branch_list_cb(const char *branch_name, void *payload)
{
branch_filter_data *filter = (branch_filter_data *)payload;
if ((filter->branch_type & GIT_BRANCH_LOCAL && git__prefixcmp(branch_name, GIT_REFS_HEADS_DIR) == 0)
|| (filter->branch_type & GIT_BRANCH_REMOTE && git__prefixcmp(branch_name, GIT_REFS_REMOTES_DIR) == 0))
return git_vector_insert(filter->branchlist, git__strdup(branch_name));
if (filter->branch_type & GIT_BRANCH_LOCAL && git__prefixcmp(branch_name, GIT_REFS_HEADS_DIR) == 0) {
return git_vector_insert(filter->branchlist, git__strdup(branch_name +strlen(GIT_REFS_HEADS_DIR)));
} else if (filter->branch_type & GIT_BRANCH_REMOTE && git__prefixcmp(branch_name, GIT_REFS_REMOTES_DIR) == 0) {
return git_vector_insert(filter->branchlist, git__strdup(branch_name+strlen(GIT_REFS_DIR)));
}
return 0;
}
......
......@@ -144,8 +144,9 @@ int git_buf_puts(git_buf *buf, const char *string)
int git_buf_vprintf(git_buf *buf, const char *format, va_list ap)
{
int len;
const size_t expected_size = buf->size + (strlen(format) * 2);
ENSURE_SIZE(buf, buf->size + (strlen(format) * 2));
ENSURE_SIZE(buf, expected_size);
while (1) {
va_list args;
......
......@@ -69,7 +69,7 @@ void *git_cache_try_store(git_cache *cache, void *_entry)
git_cached_obj *entry = _entry;
uint32_t hash;
memcpy(&hash, &entry->oid, sizeof(hash));
memcpy(&hash, &entry->oid, sizeof(uint32_t));
/* increase the refcount on this object, because
* the cache now owns it */
......
......@@ -81,66 +81,6 @@ int git_commit_create_v(
return res;
}
/* Update the reference named `ref_name` so it points to `oid` */
static int update_reference(git_repository *repo, git_oid *oid, const char *ref_name)
{
git_reference *ref;
int res;
res = git_reference_lookup(&ref, repo, ref_name);
/* If we haven't found the reference at all, we assume we need to create
* a new reference and that's it */
if (res == GIT_ENOTFOUND) {
giterr_clear();
return git_reference_create_oid(NULL, repo, ref_name, oid, 1);
}
if (res < 0)
return -1;
/* If we have found a reference, but it's symbolic, we need to update
* the direct reference it points to */
if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
git_reference *aux;
const char *sym_target;
/* The target pointed at by this reference */
sym_target = git_reference_target(ref);
/* resolve the reference to the target it points to */
res = git_reference_resolve(&aux, ref);
/*
* if the symbolic reference pointed to an inexisting ref,
* this is means we're creating a new branch, for example.
* We need to create a new direct reference with that name
*/
if (res == GIT_ENOTFOUND) {
giterr_clear();
res = git_reference_create_oid(NULL, repo, sym_target, oid, 1);
git_reference_free(ref);
return res;
}
/* free the original symbolic reference now; not before because
* we're using the `sym_target` pointer */
git_reference_free(ref);
if (res < 0)
return -1;
/* store the newly found direct reference in its place */
ref = aux;
}
/* ref is made to point to `oid`: ref is either the original reference,
* or the target of the symbolic reference we've looked up */
res = git_reference_set_oid(ref, oid);
git_reference_free(ref);
return res;
}
int git_commit_create(
git_oid *oid,
git_repository *repo,
......@@ -192,7 +132,7 @@ int git_commit_create(
git_buf_free(&commit);
if (update_ref != NULL)
return update_reference(repo, oid, update_ref);
return git_reference__update(repo, oid, update_ref);
return 0;
......
This diff is collapsed. Click to expand it.
......@@ -130,37 +130,50 @@ fail:
static git_diff_delta *diff_delta__merge_like_cgit(
const git_diff_delta *a, const git_diff_delta *b, git_pool *pool)
{
git_diff_delta *dup = diff_delta__dup(a, pool);
if (!dup)
return NULL;
if (git_oid_cmp(&dup->new_file.oid, &b->new_file.oid) == 0)
return dup;
git_oid_cpy(&dup->new_file.oid, &b->new_file.oid);
dup->new_file.mode = b->new_file.mode;
dup->new_file.size = b->new_file.size;
dup->new_file.flags = b->new_file.flags;
git_diff_delta *dup;
/* Emulate C git for merging two diffs (a la 'git diff <sha>').
*
* When C git does a diff between the work dir and a tree, it actually
* diffs with the index but uses the workdir contents. This emulates
* those choices so we can emulate the type of diff.
*
* We have three file descriptions here, let's call them:
* f1 = a->old_file
* f2 = a->new_file AND b->old_file
* f3 = b->new_file
*/
if (git_oid_cmp(&dup->old_file.oid, &dup->new_file.oid) == 0) {
if (dup->status == GIT_DELTA_DELETED)
/* preserve pending delete info */;
else if (b->status == GIT_DELTA_UNTRACKED ||
b->status == GIT_DELTA_IGNORED)
dup->status = b->status;
else
/* if f2 == f3 or f2 is deleted, then just dup the 'a' diff */
if (b->status == GIT_DELTA_UNMODIFIED || a->status == GIT_DELTA_DELETED)
return diff_delta__dup(a, pool);
/* otherwise, base this diff on the 'b' diff */
if ((dup = diff_delta__dup(b, pool)) == NULL)
return NULL;
/* If 'a' status is uninteresting, then we're done */
if (a->status == GIT_DELTA_UNMODIFIED)
return dup;
assert(a->status != GIT_DELTA_UNMODIFIED);
assert(b->status != GIT_DELTA_UNMODIFIED);
/* A cgit exception is that the diff of a file that is only in the
* index (i.e. not in HEAD nor workdir) is given as empty.
*/
if (dup->status == GIT_DELTA_DELETED) {
if (a->status == GIT_DELTA_ADDED)
dup->status = GIT_DELTA_UNMODIFIED;
/* else don't overwrite DELETE status */
} else {
dup->status = a->status;
}
else if (dup->status == GIT_DELTA_UNMODIFIED ||
b->status == GIT_DELTA_DELETED)
dup->status = b->status;
git_oid_cpy(&dup->old_file.oid, &a->old_file.oid);
dup->old_file.mode = a->old_file.mode;
dup->old_file.size = a->old_file.size;
dup->old_file.flags = a->old_file.flags;
return dup;
}
......@@ -214,7 +227,9 @@ static int diff_delta__from_two(
git_diff_list *diff,
git_delta_t status,
const git_index_entry *old_entry,
uint32_t old_mode,
const git_index_entry *new_entry,
uint32_t new_mode,
git_oid *new_oid)
{
git_diff_delta *delta;
......@@ -224,19 +239,22 @@ static int diff_delta__from_two(
return 0;
if ((diff->opts.flags & GIT_DIFF_REVERSE) != 0) {
const git_index_entry *temp = old_entry;
uint32_t temp_mode = old_mode;
const git_index_entry *temp_entry = old_entry;
old_entry = new_entry;
new_entry = temp;
new_entry = temp_entry;
old_mode = new_mode;
new_mode = temp_mode;
}
delta = diff_delta__alloc(diff, status, old_entry->path);
GITERR_CHECK_ALLOC(delta);
delta->old_file.mode = old_entry->mode;
delta->old_file.mode = old_mode;
git_oid_cpy(&delta->old_file.oid, &old_entry->oid);
delta->old_file.flags |= GIT_DIFF_FILE_VALID_OID;
delta->new_file.mode = new_entry->mode;
delta->new_file.mode = new_mode;
git_oid_cpy(&delta->new_file.oid, new_oid ? new_oid : &new_entry->oid);
if (new_oid || !git_oid_iszero(&new_entry->oid))
delta->new_file.flags |= GIT_DIFF_FILE_VALID_OID;
......@@ -300,7 +318,7 @@ static git_diff_list *git_diff_list_alloc(
if (config_bool(cfg, "core.ignorestat", 0))
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_ASSUME_UNCHANGED;
if (config_bool(cfg, "core.filemode", 1))
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_EXEC_BIT;
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_MODE_BITS;
if (config_bool(cfg, "core.trustctime", 1))
diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_CTIME;
/* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */
......@@ -419,7 +437,7 @@ static int oid_for_workdir_item(
return result;
}
#define EXEC_BIT_MASK 0000111
#define MODE_BITS_MASK 0000777
static int maybe_modified(
git_iterator *old_iter,
......@@ -443,13 +461,13 @@ static int maybe_modified(
!(diff->diffcaps & GIT_DIFFCAPS_HAS_SYMLINKS))
nmode = GIT_MODE_TYPE(omode) | (nmode & GIT_MODE_PERMS_MASK);
/* on platforms with no execmode, clear exec bit from comparisons */
if (!(diff->diffcaps & GIT_DIFFCAPS_TRUST_EXEC_BIT)) {
omode = omode & ~EXEC_BIT_MASK;
nmode = nmode & ~EXEC_BIT_MASK;
}
/* on platforms with no execmode, just preserve old mode */
if (!(diff->diffcaps & GIT_DIFFCAPS_TRUST_MODE_BITS) &&
(nmode & MODE_BITS_MASK) != (omode & MODE_BITS_MASK) &&
new_iter->type == GIT_ITERATOR_WORKDIR)
nmode = (nmode & ~MODE_BITS_MASK) | (omode & MODE_BITS_MASK);
/* support "assume unchanged" (badly, b/c we still stat everything) */
/* support "assume unchanged" (poorly, b/c we still stat everything) */
if ((diff->diffcaps & GIT_DIFFCAPS_ASSUME_UNCHANGED) != 0)
status = (oitem->flags_extended & GIT_IDXENTRY_INTENT_TO_ADD) ?
GIT_DELTA_MODIFIED : GIT_DELTA_UNMODIFIED;
......@@ -471,8 +489,13 @@ static int maybe_modified(
omode == nmode)
status = GIT_DELTA_UNMODIFIED;
/* if we have a workdir item with an unknown oid, check deeper */
else if (git_oid_iszero(&nitem->oid) && new_iter->type == GIT_ITERATOR_WORKDIR) {
/* if modes match and we have an unknown OID and a workdir iterator,
* then check deeper for matching
*/
else if (omode == nmode &&
git_oid_iszero(&nitem->oid) &&
new_iter->type == GIT_ITERATOR_WORKDIR)
{
/* TODO: add check against index file st_mtime to avoid racy-git */
/* if they files look exactly alike, then we'll assume the same */
......@@ -517,7 +540,8 @@ static int maybe_modified(
use_noid = &noid;
}
return diff_delta__from_two(diff, status, oitem, nitem, use_noid);
return diff_delta__from_two(
diff, status, oitem, omode, nitem, nmode, use_noid);
}
static int diff_from_iterators(
......@@ -772,6 +796,12 @@ int git_diff_merge(
git_vector_swap(&onto->deltas, &onto_new);
git_pool_swap(&onto->pool, &onto_pool);
onto->new_src = from->new_src;
/* prefix strings also come from old pool, so recreate those.*/
onto->opts.old_prefix =
git_pool_strdup(&onto->pool, onto->opts.old_prefix);
onto->opts.new_prefix =
git_pool_strdup(&onto->pool, onto->opts.new_prefix);
}
git_vector_foreach(&onto_new, i, delta)
......
......@@ -20,7 +20,7 @@
enum {
GIT_DIFFCAPS_HAS_SYMLINKS = (1 << 0), /* symlinks on platform? */
GIT_DIFFCAPS_ASSUME_UNCHANGED = (1 << 1), /* use stat? */
GIT_DIFFCAPS_TRUST_EXEC_BIT = (1 << 2), /* use st_mode exec bit? */
GIT_DIFFCAPS_TRUST_MODE_BITS = (1 << 2), /* use st_mode? */
GIT_DIFFCAPS_TRUST_CTIME = (1 << 3), /* use st_ctime? */
GIT_DIFFCAPS_USE_DEV = (1 << 4), /* use st_dev? */
};
......@@ -36,5 +36,8 @@ struct git_diff_list {
uint32_t diffcaps;
};
extern void git_diff__cleanup_modes(
uint32_t diffcaps, uint32_t *omode, uint32_t *nmode);
#endif
......@@ -83,12 +83,13 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
info->cb_data, info->delta, &info->range, origin, bufs[1].ptr, bufs[1].size) < 0)
return -1;
/* deal with adding and removing newline at EOF */
/* This should only happen if we are adding a line that does not
* have a newline at the end and the old code did. In that case,
* we have a ADD with a DEL_EOFNL as a pair.
*/
if (len == 3) {
if (origin == GIT_DIFF_LINE_ADDITION)
origin = GIT_DIFF_LINE_ADD_EOFNL;
else
origin = GIT_DIFF_LINE_DEL_EOFNL;
origin = (origin == GIT_DIFF_LINE_ADDITION) ?
GIT_DIFF_LINE_DEL_EOFNL : GIT_DIFF_LINE_ADD_EOFNL;
return info->line_cb(
info->cb_data, info->delta, &info->range, origin, bufs[2].ptr, bufs[2].size);
......@@ -359,7 +360,7 @@ int git_diff_foreach(
/* map files */
if (delta->binary != 1 &&
(hunk_cb || line_cb) &&
(hunk_cb || line_cb || git_oid_iszero(&delta->old_file.oid)) &&
(delta->status == GIT_DELTA_DELETED ||
delta->status == GIT_DELTA_MODIFIED))
{
......@@ -397,7 +398,9 @@ int git_diff_foreach(
/* since we did not have the definitive oid, we may have
* incorrect status and need to skip this item.
*/
if (git_oid_cmp(&delta->old_file.oid, &delta->new_file.oid) == 0) {
if (delta->old_file.mode == delta->new_file.mode &&
!git_oid_cmp(&delta->old_file.oid, &delta->new_file.oid))
{
delta->status = GIT_DELTA_UNMODIFIED;
if ((diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0)
goto cleanup;
......@@ -420,7 +423,8 @@ int git_diff_foreach(
*/
if (file_cb != NULL) {
error = file_cb(data, delta, (float)info.index / diff->deltas.length);
error = file_cb(
data, delta, (float)info.index / diff->deltas.length);
if (error < 0)
goto cleanup;
}
......@@ -433,6 +437,10 @@ int git_diff_foreach(
if (!old_data.len && !new_data.len)
goto cleanup;
/* nothing to do if only diff was a mode change */
if (!git_oid_cmp(&delta->old_file.oid, &delta->new_file.oid))
goto cleanup;
assert(hunk_cb || line_cb);
info.delta = delta;
......@@ -467,7 +475,7 @@ static char pick_suffix(int mode)
{
if (S_ISDIR(mode))
return '/';
else if (mode & 0100)
else if (mode & 0100) //-V536
/* in git, modes are very regular, so we must have 0100755 mode */
return '*';
else
......
......@@ -28,6 +28,8 @@ static int parse_ignore_file(
GITERR_CHECK_ALLOC(match);
}
match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE;
if (!(error = git_attr_fnmatch__parse(
match, ignores->pool, context, &scan)))
{
......
......@@ -292,11 +292,13 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz
{
int error;
struct git_pack_header hdr;
size_t processed = stats->processed;
size_t processed;
git_mwindow_file *mwf = &idx->pack->mwf;
assert(idx && data && stats);
processed = stats->processed;
if (git_filebuf_write(&idx->pack_file, data, size) < 0)
return -1;
......
......@@ -125,7 +125,7 @@ static int note_write(git_oid *out, git_repository *repo,
return error;
}
error = git_treebuilder_insert(&entry, tb, target + fanout, &oid, 0100644);
error = git_treebuilder_insert(&entry, tb, target + fanout, &oid, 0100644); //-V536
if (error < 0) {
/* libgit2 doesn't support object removal (gc) yet */
/* we leave an orphaned blob object behind - TODO */
......@@ -154,7 +154,7 @@ static int note_write(git_oid *out, git_repository *repo,
if (error < 0)
return error;
error = git_treebuilder_insert(NULL, tb, subtree, &oid, 0040000);
error = git_treebuilder_insert(NULL, tb, subtree, &oid, 0040000); //-V536
if (error < 0) {
git_treebuilder_free(tb);
return error;
......
......@@ -17,6 +17,10 @@
#include <stdio.h>
#include <ctype.h>
#ifdef GIT_WIN32
#define LOOKS_LIKE_DRIVE_PREFIX(S) (git__isalpha((S)[0]) && (S)[1] == ':')
#endif
/*
* Based on the Android implementation, BSD licensed.
* Check http://android.git.kernel.org/
......@@ -105,7 +109,7 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
/* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return
'C:/' here */
if (len == 2 && isalpha(path[0]) && path[1] == ':') {
if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) {
len = 3;
goto Exit;
}
......@@ -170,7 +174,7 @@ int git_path_root(const char *path)
#ifdef GIT_WIN32
/* Does the root of the path look like a windows drive ? */
if (isalpha(path[0]) && (path[1] == ':'))
if (LOOKS_LIKE_DRIVE_PREFIX(path))
offset += 2;
/* Are we dealing with a windows network path? */
......@@ -210,7 +214,7 @@ int git_path_prettify(git_buf *path_out, const char *path, const char *base)
giterr_set(GITERR_OS, "Failed to resolve path '%s'", path);
git_buf_clear(path_out);
return error;
}
......
......@@ -59,9 +59,18 @@ extern int p_rename(const char *from, const char *to);
typedef int GIT_SOCKET;
#define INVALID_SOCKET -1
#define p_localtime_r localtime_r
#define p_gmtime_r gmtime_r
#define p_gettimeofday gettimeofday
#else
typedef SOCKET GIT_SOCKET;
struct timezone;
extern struct tm * p_localtime_r (const time_t *timer, struct tm *result);
extern struct tm * p_gmtime_r (const time_t *timer, struct tm *result);
extern int p_gettimeofday(struct timeval *tv, struct timezone *tz);
#endif
......
......@@ -1705,3 +1705,62 @@ int git_reference_cmp(git_reference *ref1, git_reference *ref2)
return git_oid_cmp(&ref1->target.oid, &ref2->target.oid);
}
/* Update the reference named `ref_name` so it points to `oid` */
int git_reference__update(git_repository *repo, const git_oid *oid, const char *ref_name)
{
git_reference *ref;
int res;
res = git_reference_lookup(&ref, repo, ref_name);
/* If we haven't found the reference at all, we assume we need to create
* a new reference and that's it */
if (res == GIT_ENOTFOUND) {
giterr_clear();
return git_reference_create_oid(NULL, repo, ref_name, oid, 1);
}
if (res < 0)
return -1;
/* If we have found a reference, but it's symbolic, we need to update
* the direct reference it points to */
if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
git_reference *aux;
const char *sym_target;
/* The target pointed at by this reference */
sym_target = git_reference_target(ref);
/* resolve the reference to the target it points to */
res = git_reference_resolve(&aux, ref);
/*
* if the symbolic reference pointed to an inexisting ref,
* this is means we're creating a new branch, for example.
* We need to create a new direct reference with that name
*/
if (res == GIT_ENOTFOUND) {
giterr_clear();
res = git_reference_create_oid(NULL, repo, sym_target, oid, 1);
git_reference_free(ref);
return res;
}
/* free the original symbolic reference now; not before because
* we're using the `sym_target` pointer */
git_reference_free(ref);
if (res < 0)
return -1;
/* store the newly found direct reference in its place */
ref = aux;
}
/* ref is made to point to `oid`: ref is either the original reference,
* or the target of the symbolic reference we've looked up */
res = git_reference_set_oid(ref, oid);
git_reference_free(ref);
return res;
}
......@@ -54,6 +54,7 @@ void git_repository__refcache_free(git_refcache *refs);
int git_reference__normalize_name(char *buffer_out, size_t out_size, const char *name);
int git_reference__normalize_name_oid(char *buffer_out, size_t out_size, const char *name);
int git_reference__update(git_repository *repo, const git_oid *oid, const char *ref_name);
/**
* Lookup a reference by name and try to resolve to an OID.
......
......@@ -337,13 +337,16 @@ int git_remote_update_tips(git_remote *remote, int (*cb)(const char *refname, co
unsigned int i = 0;
git_buf refname = GIT_BUF_INIT;
git_oid old;
git_vector *refs = &remote->refs;
git_vector *refs;
git_remote_head *head;
git_reference *ref;
struct git_refspec *spec = &remote->fetch;
struct git_refspec *spec;
assert(remote);
refs = &remote->refs;
spec = &remote->fetch;
if (refs->length == 0)
return 0;
......
......@@ -718,6 +718,9 @@ static int repo_init_config(const char *git_dir, bool is_bare, bool is_reinit)
SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION);
SET_REPO_CONFIG(bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path)));
if (!is_bare)
SET_REPO_CONFIG(bool, "core.logallrefupdates", true);
if (!is_reinit && is_filesystem_case_insensitive(git_dir))
SET_REPO_CONFIG(bool, "core.ignorecase", true);
/* TODO: what other defaults? */
......
/*
* Copyright (C) 2009-2012 the libgit2 contributors
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "common.h"
#include "commit.h"
#include "tag.h"
#include "git2/reset.h"
#define ERROR_MSG "Cannot perform reset"
static int reset_error_invalid(const char *msg)
{
giterr_set(GITERR_INVALID, "%s - %s", ERROR_MSG, msg);
return -1;
}
int git_reset(
git_repository *repo,
const git_object *target,
git_reset_type reset_type)
{
git_otype target_type = GIT_OBJ_BAD;
git_object *commit = NULL;
git_index *index = NULL;
git_tree *tree = NULL;
int error = -1;
assert(repo && target);
assert(reset_type == GIT_RESET_SOFT || reset_type == GIT_RESET_MIXED);
if (git_object_owner(target) != repo)
return reset_error_invalid("The given target does not belong to this repository.");
if (reset_type == GIT_RESET_MIXED && git_repository_is_bare(repo))
return reset_error_invalid("Mixed reset is not allowed in a bare repository.");
target_type = git_object_type(target);
switch (target_type)
{
case GIT_OBJ_TAG:
if (git_tag_peel(&commit, (git_tag *)target) < 0)
goto cleanup;
if (git_object_type(commit) != GIT_OBJ_COMMIT) {
reset_error_invalid("The given target does not resolve to a commit.");
goto cleanup;
}
break;
case GIT_OBJ_COMMIT:
commit = (git_object *)target;
break;
default:
return reset_error_invalid("Only git_tag and git_commit objects are valid targets.");
}
//TODO: Check for unmerged entries
if (git_reference__update(repo, git_object_id(commit), GIT_HEAD_FILE) < 0)
goto cleanup;
if (reset_type == GIT_RESET_SOFT) {
error = 0;
goto cleanup;
}
if (git_commit_tree(&tree, (git_commit *)commit) < 0) {
giterr_set(GITERR_OBJECT, "%s - Failed to retrieve the commit tree.", ERROR_MSG);
goto cleanup;
}
if (git_repository_index(&index, repo) < 0) {
giterr_set(GITERR_OBJECT, "%s - Failed to retrieve the index.", ERROR_MSG);
goto cleanup;
}
if (git_index_read_tree(index, tree) < 0) {
giterr_set(GITERR_INDEX, "%s - Failed to update the index.", ERROR_MSG);
goto cleanup;
}
if (git_index_write(index) < 0) {
giterr_set(GITERR_INDEX, "%s - Failed to write the index.", ERROR_MSG);
goto cleanup;
}
error = 0;
cleanup:
if (target_type == GIT_OBJ_TAG)
git_object_free(commit);
git_index_free(index);
git_tree_free(tree);
return error;
}
This diff is collapsed. Click to expand it.
......@@ -169,14 +169,23 @@ static commit_object *commit_lookup(git_revwalk *walk, const git_oid *oid)
return commit;
}
static int commit_error(commit_object *commit, const char *msg)
{
char commit_oid[GIT_OID_HEXSZ + 1];
git_oid_fmt(commit_oid, &commit->oid);
commit_oid[GIT_OID_HEXSZ] = '\0';
giterr_set(GITERR_ODB, "Failed to parse commit %s - %s", commit_oid, msg);
return -1;
}
static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawobj *raw)
{
const size_t parent_len = strlen("parent ") + GIT_OID_HEXSZ + 1;
unsigned char *buffer = raw->data;
unsigned char *buffer_end = buffer + raw->len;
unsigned char *parents_start;
int i, parents = 0;
int commit_time;
......@@ -207,21 +216,18 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
commit->out_degree = (unsigned short)parents;
if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) {
giterr_set(GITERR_ODB, "Failed to parse commit. Object is corrupted");
return -1;
}
if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
return commit_error(commit, "object is corrupted");
buffer = memchr(buffer, '>', buffer_end - buffer);
if (buffer == NULL) {
giterr_set(GITERR_ODB, "Failed to parse commit. Can't find author");
return -1;
}
if ((buffer = memchr(buffer, '<', buffer_end - buffer)) == NULL ||
(buffer = memchr(buffer, '>', buffer_end - buffer)) == NULL)
return commit_error(commit, "malformed author information");
if (git__strtol32(&commit_time, (char *)buffer + 2, NULL, 10) < 0) {
giterr_set(GITERR_ODB, "Failed to parse commit. Can't parse commit time");
return -1;
}
while (*buffer == '>' || git__isspace(*buffer))
buffer++;
if (git__strtol32(&commit_time, (char *)buffer, NULL, 10) < 0)
return commit_error(commit, "cannot parse commit time");
commit->time = (time_t)commit_time;
commit->parsed = 1;
......
......@@ -113,26 +113,14 @@ int git_signature_now(git_signature **sig_out, const char *name, const char *ema
time_t offset;
struct tm *utc_tm, *local_tm;
git_signature *sig;
#ifndef GIT_WIN32
struct tm _utc, _local;
#endif
*sig_out = NULL;
time(&now);
/**
* On Win32, `gmtime_r` doesn't exist but
* `gmtime` is threadsafe, so we can use that
*/
#ifdef GIT_WIN32
utc_tm = gmtime(&now);
local_tm = localtime(&now);
#else
utc_tm = gmtime_r(&now, &_utc);
local_tm = localtime_r(&now, &_local);
#endif
utc_tm = p_gmtime_r(&now, &_utc);
local_tm = p_localtime_r(&now, &_local);
offset = mktime(local_tm) - mktime(utc_tm);
offset /= 60;
......
......@@ -69,7 +69,7 @@ const git_tree_cache *git_tree_cache_get(const git_tree_cache *tree, const char
return NULL;
}
if (end == NULL || end + 1 == '\0')
if (end == NULL || *end + 1 == '\0')
return tree;
ptr = end + 1;
......
......@@ -22,7 +22,7 @@ static int valid_attributes(const int attributes)
static int valid_entry_name(const char *filename)
{
return strlen(filename) > 0 && strchr(filename, '/') == NULL;
return *filename != '\0' && strchr(filename, '/') == NULL;
}
static int entry_sort_cmp(const void *a, const void *b)
......
......@@ -209,6 +209,13 @@ GIT_INLINE(bool) git__isspace(int c)
return (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == '\v');
}
GIT_INLINE(int) git__time_cmp(const git_time *a, const git_time *b)
{
/* Adjust for time zones. Times are in seconds, offsets are in minutes. */
git_time_t adjusted_a = a->time + ((b->offset - a->offset) * 60);
return (int)(adjusted_a - b->time);
}
GIT_INLINE(bool) git__iswildcard(int c)
{
return (c == '*' || c == '?' || c == '[');
......@@ -223,4 +230,14 @@ GIT_INLINE(bool) git__iswildcard(int c)
*/
extern int git__parse_bool(int *out, const char *value);
/*
* Parse a string into a value as a git_time_t.
*
* Sample valid input:
* - "yesterday"
* - "July 17, 2003"
* - "2003-7-17 08:23"
*/
int git__date_parse(git_time_t *out, const char *date);
#endif /* INCLUDE_util_h__ */
......@@ -414,7 +414,7 @@ int p_mkstemp(char *tmp_path)
return -1;
#endif
return p_creat(tmp_path, 0744);
return p_creat(tmp_path, 0744); //-V536
}
int p_setenv(const char* name, const char* value, int overwrite)
......@@ -470,3 +470,79 @@ int p_send(GIT_SOCKET socket, const void *buffer, size_t length, int flags)
return send(socket, buffer, (int)length, flags);
}
/**
* Borrowed from http://old.nabble.com/Porting-localtime_r-and-gmtime_r-td15282276.html
* On Win32, `gmtime_r` doesn't exist but `gmtime` is threadsafe, so we can use that
*/
struct tm *
p_localtime_r (const time_t *timer, struct tm *result)
{
struct tm *local_result;
local_result = localtime (timer);
if (local_result == NULL || result == NULL)
return NULL;
memcpy (result, local_result, sizeof (struct tm));
return result;
}
struct tm *
p_gmtime_r (const time_t *timer, struct tm *result)
{
struct tm *local_result;
local_result = gmtime (timer);
if (local_result == NULL || result == NULL)
return NULL;
memcpy (result, local_result, sizeof (struct tm));
return result;
}
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
int p_gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv)
{
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
/*converting file time to unix epoch*/
tmpres /= 10; /*convert into microseconds*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
}
if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
#include "precompiled.h"
\ No newline at end of file
#include "git2.h"
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <regex.h>
#include <io.h>
#include <direct.h>
#ifdef GIT_THREADS
#include "win32/pthread.h"
#endif
......@@ -48,6 +48,62 @@ void cl_git_rewritefile(const char *filename, const char *new_content)
cl_git_write2file(filename, new_content, O_WRONLY | O_CREAT | O_TRUNC);
}
#ifdef GIT_WIN32
#include "win32/utf-conv.h"
char *cl_getenv(const char *name)
{
wchar_t *name_utf16 = gitwin_to_utf16(name);
DWORD value_len, alloc_len;
wchar_t *value_utf16;
char *value_utf8;
cl_assert(name_utf16);
alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0);
if (alloc_len <= 0)
return NULL;
cl_assert(value_utf16 = git__calloc(alloc_len, sizeof(wchar_t)));
value_len = GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len);
cl_assert_equal_i(value_len, alloc_len - 1);
cl_assert(value_utf8 = gitwin_from_utf16(value_utf16));
git__free(value_utf16);
return value_utf8;
}
int cl_setenv(const char *name, const char *value)
{
wchar_t *name_utf16 = gitwin_to_utf16(name);
wchar_t *value_utf16 = value ? gitwin_to_utf16(value) : NULL;
cl_assert(name_utf16);
cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16));
git__free(name_utf16);
git__free(value_utf16);
return 0;
}
#else
#include <stdlib.h>
char *cl_getenv(const char *name)
{
return getenv(name);
}
int cl_setenv(const char *name, const char *value)
{
return (value == NULL) ? unsetenv(name) : setenv(name, value, 1);
}
#endif
static const char *_cl_sandbox = NULL;
static git_repository *_cl_repo = NULL;
......@@ -98,3 +154,28 @@ void cl_git_sandbox_cleanup(void)
_cl_sandbox = NULL;
}
}
bool cl_toggle_filemode(const char *filename)
{
struct stat st1, st2;
cl_must_pass(p_stat(filename, &st1));
cl_must_pass(p_chmod(filename, st1.st_mode ^ 0100));
cl_must_pass(p_stat(filename, &st2));
return (st1.st_mode != st2.st_mode);
}
bool cl_is_chmod_supported(void)
{
static int _is_supported = -1;
if (_is_supported < 0) {
cl_git_mkfile("filemode.t", "Test if filemode can be modified");
_is_supported = cl_toggle_filemode("filemode.t");
cl_must_pass(p_unlink("filemode.t"));
}
return _is_supported;
}
......@@ -40,6 +40,13 @@ void cl_git_append2file(const char *filename, const char *new_content);
void cl_git_rewritefile(const char *filename, const char *new_content);
void cl_git_write2file(const char *filename, const char *new_content, int mode);
bool cl_toggle_filemode(const char *filename);
bool cl_is_chmod_supported(void);
/* Environment wrappers */
char *cl_getenv(const char *name);
int cl_setenv(const char *name, const char *value);
/* Git sandbox setup helpers */
git_repository *cl_git_sandbox_init(const char *sandbox);
......
......@@ -3,59 +3,6 @@
#include "path.h"
#ifdef GIT_WIN32
#include "win32/utf-conv.h"
static char *cl_getenv(const char *name)
{
wchar_t *name_utf16 = gitwin_to_utf16(name);
DWORD value_len, alloc_len;
wchar_t *value_utf16;
char *value_utf8;
cl_assert(name_utf16);
alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0);
if (alloc_len <= 0)
return NULL;
cl_assert(value_utf16 = git__calloc(alloc_len, sizeof(wchar_t)));
value_len = GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len);
cl_assert_equal_i(value_len, alloc_len - 1);
cl_assert(value_utf8 = gitwin_from_utf16(value_utf16));
git__free(value_utf16);
return value_utf8;
}
static int cl_setenv(const char *name, const char *value)
{
wchar_t *name_utf16 = gitwin_to_utf16(name);
wchar_t *value_utf16 = value ? gitwin_to_utf16(value) : NULL;
cl_assert(name_utf16);
cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16));
git__free(name_utf16);
git__free(value_utf16);
return 0;
}
#else
#include <stdlib.h>
#define cl_getenv(n) getenv(n)
static int cl_setenv(const char *name, const char *value)
{
return (value == NULL) ? unsetenv(name) : setenv(name, value, 1);
}
#endif
#ifdef GIT_WIN32
static char *env_userprofile = NULL;
static char *env_programfiles = NULL;
#else
......
......@@ -8,7 +8,7 @@ void test_core_filebuf__0(void)
int fd;
char test[] = "test", testlock[] = "test.lock";
fd = p_creat(testlock, 0744);
fd = p_creat(testlock, 0744); //-V536
cl_must_pass(fd);
cl_must_pass(p_close(fd));
......@@ -27,7 +27,7 @@ void test_core_filebuf__1(void)
int fd;
char test[] = "test";
fd = p_creat(test, 0666);
fd = p_creat(test, 0666); //-V536
cl_must_pass(fd);
cl_must_pass(p_write(fd, "libgit2 rocks\n", 14));
cl_must_pass(p_close(fd));
......
#include "clar_libgit2.h"
#include "util.h"
void test_date_date__overflow(void)
{
#ifdef __LP64__
git_time_t d2038, d2039;
/* This is expected to fail on a 32-bit machine. */
cl_git_pass(git__date_parse(&d2038, "2038-1-1"));
cl_git_pass(git__date_parse(&d2039, "2039-1-1"));
cl_assert(d2038 < d2039);
#endif
}
......@@ -85,11 +85,16 @@ int diff_line_fn(
e->line_ctxt++;
break;
case GIT_DIFF_LINE_ADDITION:
case GIT_DIFF_LINE_ADD_EOFNL:
e->line_adds++;
break;
case GIT_DIFF_LINE_ADD_EOFNL:
assert(0);
break;
case GIT_DIFF_LINE_DELETION:
e->line_dels++;
break;
case GIT_DIFF_LINE_DEL_EOFNL:
/* technically not a line delete, but we'll count it as such */
e->line_dels++;
break;
default:
......
......@@ -116,7 +116,7 @@ void test_diff_tree__options(void)
{ 5, 3, 0, 2, 0, 0, 0, 4, 0, 0, 51, 2, 46, 3 },
{ 5, 3, 0, 2, 0, 0, 0, 4, 0, 0, 53, 4, 46, 3 },
{ 5, 0, 3, 2, 0, 0, 0, 4, 0, 0, 52, 3, 3, 46 },
{ 5, 3, 0, 2, 0, 0, 0, 5, 0, 0, 54, 3, 48, 3 },
{ 5, 3, 0, 2, 0, 0, 0, 5, 0, 0, 54, 3, 47, 4 },
/* c vs d tests */
{ 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 22, 9, 10, 3 },
{ 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 19, 12, 7, 0 },
......
......@@ -33,7 +33,7 @@ static void copy_file(const char *src, const char *dst)
cl_git_pass(git_futils_readbuffer(&source_buf, src));
dst_fd = git_futils_creat_withpath(dst, 0777, 0666);
dst_fd = git_futils_creat_withpath(dst, 0777, 0666); //-V536
if (dst_fd < 0)
goto cleanup;
......
......@@ -107,7 +107,7 @@ void test_network_remotelocal__retrieve_advertised_references(void)
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs));
cl_assert(how_many_refs == 14); /* 1 HEAD + 6 heads + 1 lightweight tag + 3 annotated tags + 3 peeled target */
cl_assert_equal_i(how_many_refs, 20);
}
void test_network_remotelocal__retrieve_advertised_references_from_spaced_repository(void)
......@@ -121,7 +121,7 @@ void test_network_remotelocal__retrieve_advertised_references_from_spaced_reposi
cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs));
cl_assert(how_many_refs == 14); /* 1 HEAD + 6 heads + 1 lightweight tag + 3 annotated tags + 3 peeled target */
cl_assert_equal_i(how_many_refs, 20);
git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */
remote = NULL;
......
......@@ -63,14 +63,14 @@ void test_object_tree_write__subtree(void)
//create subtree
cl_git_pass(git_treebuilder_create(&builder, NULL));
cl_git_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644));
cl_git_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644)); //-V536
cl_git_pass(git_treebuilder_write(&subtree_id, g_repo, builder));
git_treebuilder_free(builder);
// create parent tree
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
cl_git_pass(git_treebuilder_create(&builder, tree));
cl_git_pass(git_treebuilder_insert(NULL,builder,"new",&subtree_id,040000));
cl_git_pass(git_treebuilder_insert(NULL,builder,"new",&subtree_id,040000)); //-V536
cl_git_pass(git_treebuilder_write(&id_hiearar, g_repo, builder));
git_treebuilder_free(builder);
git_tree_free(tree);
......
......@@ -30,22 +30,22 @@ static void assert_retrieval(unsigned int flags, unsigned int expected_count)
{
cl_git_pass(git_branch_list(&branch_list, repo, flags));
cl_assert_equal_i(expected_count, branch_list.count);
cl_assert_equal_i(branch_list.count, expected_count);
}
void test_refs_branches_listall__retrieve_all_branches(void)
{
assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 6 + 1);
assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 9);
}
void test_refs_branches_listall__retrieve_remote_branches(void)
{
assert_retrieval(GIT_BRANCH_REMOTE, 1);
assert_retrieval(GIT_BRANCH_REMOTE, 2);
}
void test_refs_branches_listall__retrieve_local_branches(void)
{
assert_retrieval(GIT_BRANCH_LOCAL, 6);
assert_retrieval(GIT_BRANCH_LOCAL, 7);
}
static void assert_branch_list_contains(git_strarray *branches, const char* expected_branch_name)
......@@ -72,7 +72,7 @@ void test_refs_branches_listall__retrieve_remote_symbolic_HEAD_when_present(void
cl_git_pass(git_branch_list(&branch_list, repo, GIT_BRANCH_REMOTE));
cl_assert_equal_i(2, branch_list.count);
assert_branch_list_contains(&branch_list, "refs/remotes/nulltoken/HEAD");
assert_branch_list_contains(&branch_list, "refs/remotes/nulltoken/master");
cl_assert_equal_i(3, branch_list.count);
assert_branch_list_contains(&branch_list, "remotes/nulltoken/HEAD");
assert_branch_list_contains(&branch_list, "remotes/nulltoken/master");
}
#include "clar_libgit2.h"
#include "git2/revparse.h"
static git_repository *g_repo;
static git_object *g_obj;
static char g_orig_tz[16] = {0};
/* Helpers */
static void test_object(const char *spec, const char *expected_oid)
{
char objstr[64] = {0};
cl_git_pass(git_revparse_single(&g_obj, g_repo, spec));
git_oid_fmt(objstr, git_object_id(g_obj));
cl_assert_equal_s(objstr, expected_oid);
git_object_free(g_obj);
g_obj = NULL;
}
void test_refs_revparse__initialize(void)
{
char *tz = cl_getenv("TZ");
if (tz)
strcpy(g_orig_tz, tz);
cl_setenv("TZ", "UTC");
g_repo = cl_git_sandbox_init("testrepo.git");
}
void test_refs_revparse__cleanup(void)
{
cl_git_sandbox_cleanup();
g_obj = NULL;
cl_setenv("TZ", g_orig_tz);
}
void test_refs_revparse__nonexistant_object(void)
{
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't exist"));
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't exist^1"));
cl_git_fail(git_revparse_single(&g_obj, g_repo, "this doesn't exist~2"));
}
void test_refs_revparse__shas(void)
{
test_object("c47800c7266a2be04c571c04d5a6614691ea99bd", "c47800c7266a2be04c571c04d5a6614691ea99bd");
test_object("c47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd");
}
void test_refs_revparse__head(void)
{
test_object("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
}
void test_refs_revparse__full_refs(void)
{
test_object("refs/heads/master", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("refs/heads/test", "e90810b8df3e80c413d903f631643c716887138d");
test_object("refs/tags/test", "b25fa35b38051e4ae45d4222e795f9df2e43f1d1");
}
void test_refs_revparse__partial_refs(void)
{
test_object("point_to_blob", "1385f264afb75a56a5bec74243be9b367ba4ca08");
test_object("packed-test", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045");
test_object("br2", "a4a7dce85cf63874e984719f4fdd239f5145052f");
}
void test_refs_revparse__describe_output(void)
{
test_object("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd");
test_object("not-good", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
}
void test_refs_revparse__nth_parent(void)
{
test_object("be3563a^1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
test_object("be3563a^", "9fd738e8f7967c078dceed8190330fc8648ee56a");
test_object("be3563a^2", "c47800c7266a2be04c571c04d5a6614691ea99bd");
test_object("be3563a^1^1", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045");
test_object("be3563a^2^1", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
test_object("be3563a^0", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
}
void test_refs_revparse__not_tag(void)
{
test_object("point_to_blob^{}", "1385f264afb75a56a5bec74243be9b367ba4ca08");
test_object("wrapped_tag^{}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
}
void test_refs_revparse__to_type(void)
{
test_object("wrapped_tag^{commit}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("wrapped_tag^{tree}", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162");
test_object("point_to_blob^{blob}", "1385f264afb75a56a5bec74243be9b367ba4ca08");
cl_git_fail(git_revparse_single(&g_obj, g_repo, "wrapped_tag^{blob}"));
}
void test_refs_revparse__linear_history(void)
{
test_object("master~0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("master~1", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("master~2", "9fd738e8f7967c078dceed8190330fc8648ee56a");
test_object("master~1~1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
}
void test_refs_revparse__chaining(void)
{
test_object("master~1^1", "9fd738e8f7967c078dceed8190330fc8648ee56a");
test_object("master~1^2", "c47800c7266a2be04c571c04d5a6614691ea99bd");
test_object("master^1^2~1", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
test_object("master^1^1^1^1^1", "8496071c1b46c854b31185ea97743be6a8774479");
}
void test_refs_revparse__reflog(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, "@{1000}"));
test_object("@{-2}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("@{-1}", "a4a7dce85cf63874e984719f4fdd239f5145052f");
test_object("master@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
}
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^{/anoth}", "5b5b025afb0b4c913b4c338a42934a3863bf3644");
test_object("master^{/Merge}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("br2^{/Merge}", "a4a7dce85cf63874e984719f4fdd239f5145052f");
test_object("master^{/fo.rth}", "9fd738e8f7967c078dceed8190330fc8648ee56a");
}
void test_refs_revparse__date(void)
{
test_object("HEAD@{10 years ago}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("master@{2012-4-30 10:23:20 -0800}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("master@{2012-4-30 18:24 -0800}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("master@{2012-4-30 23:24 -0300}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
/* Core git gives a65fedf, because they don't take time zones into account. */
test_object("master@{1335806640}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
}
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, ":/not found in any commit"));
cl_git_fail(git_revparse_single(&g_obj, g_repo, ":2:README"));
test_object("subtrees:ab/4.txt", "d6c93164c249c8000205dd4ec5cbca1b516d487f");
test_object("subtrees:ab/de/fgh/1.txt", "1f67fc4386b2d171e0d21be1c447e12660561f9b");
test_object("master:README", "a8233120f6ad708f843d861ce2b7228ec4e3dec6");
test_object("master:new.txt", "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd");
test_object(":/Merge", "a4a7dce85cf63874e984719f4fdd239f5145052f");
test_object(":/one", "c47800c7266a2be04c571c04d5a6614691ea99bd");
test_object(":/packed commit t", "41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9");
}
......@@ -166,14 +166,14 @@ void test_repo_init__additional_templates(void)
git_buf_free(&path);
}
static void assert_config_entry_on_init(const char *config_key, int expected_value)
static void assert_config_entry_on_init_bytype(const char *config_key, int expected_value, bool is_bare)
{
git_config *config;
int current_value;
cl_set_cleanup(&cleanup_repository, "config_entry");
cl_git_pass(git_repository_init(&_repo, "config_entry/test.git", 1));
cl_git_pass(git_repository_init(&_repo, "config_entry/test.git", is_bare));
git_repository_config(&config, _repo);
if (expected_value >= 0) {
......@@ -189,6 +189,14 @@ static void assert_config_entry_on_init(const char *config_key, int expected_val
git_config_free(config);
}
static void assert_config_entry_on_init(const char *config_key, int expected_value)
{
assert_config_entry_on_init_bytype(config_key, expected_value, true);
git_repository_free(_repo);
assert_config_entry_on_init_bytype(config_key, expected_value, false);
}
void test_repo_init__detect_filemode(void)
{
#ifdef GIT_WIN32
......@@ -233,3 +241,9 @@ void test_repo_init__reinit_doesnot_overwrite_ignorecase(void)
git_config_free(config);
}
void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void)
{
assert_config_entry_on_init_bytype("core.logallrefupdates", GIT_ENOTFOUND, true);
assert_config_entry_on_init_bytype("core.logallrefupdates", true, false);
}
#include "clar_libgit2.h"
#include "posix.h"
#include "reset_helpers.h"
#include "path.h"
static git_repository *repo;
static git_object *target;
void test_reset_mixed__initialize(void)
{
repo = cl_git_sandbox_init("attr");
target = NULL;
}
void test_reset_mixed__cleanup(void)
{
git_object_free(target);
cl_git_sandbox_cleanup();
}
void test_reset_mixed__cannot_reset_in_a_bare_repository(void)
{
git_repository *bare;
cl_git_pass(git_repository_open(&bare, cl_fixture("testrepo.git")));
cl_assert(git_repository_is_bare(bare) == true);
retrieve_target_from_oid(&target, bare, KNOWN_COMMIT_IN_BARE_REPO);
cl_git_fail(git_reset(bare, target, GIT_RESET_MIXED));
git_repository_free(bare);
}
void test_reset_mixed__resetting_refreshes_the_index_to_the_commit_tree(void)
{
unsigned int status;
cl_git_pass(git_status_file(&status, repo, "macro_bad"));
cl_assert(status == GIT_STATUS_CURRENT);
retrieve_target_from_oid(&target, repo, "605812ab7fe421fdd325a935d35cb06a9234a7d7");
cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED));
cl_git_pass(git_status_file(&status, repo, "macro_bad"));
cl_assert(status == GIT_STATUS_WT_NEW);
}
#include "clar_libgit2.h"
#include "reset_helpers.h"
void retrieve_target_from_oid(git_object **object_out, git_repository *repo, const char *sha)
{
git_oid oid;
cl_git_pass(git_oid_fromstr(&oid, sha));
cl_git_pass(git_object_lookup(object_out, repo, &oid, GIT_OBJ_ANY));
}
#include "common.h"
#define KNOWN_COMMIT_IN_BARE_REPO "e90810b8df3e80c413d903f631643c716887138d"
#define KNOWN_COMMIT_IN_ATTR_REPO "217878ab49e1314388ea2e32dc6fdb58a1b969e0"
extern void retrieve_target_from_oid(git_object **object_out, git_repository *repo, const char *sha);
#include "clar_libgit2.h"
#include "reset_helpers.h"
static git_repository *repo;
static git_object *target;
void test_reset_soft__initialize(void)
{
repo = cl_git_sandbox_init("testrepo.git");
}
void test_reset_soft__cleanup(void)
{
git_object_free(target);
cl_git_sandbox_cleanup();
}
static void assert_reset_soft(bool should_be_detached)
{
git_oid oid;
cl_git_pass(git_reference_name_to_oid(&oid, repo, "HEAD"));
cl_git_fail(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO));
retrieve_target_from_oid(&target, repo, KNOWN_COMMIT_IN_BARE_REPO);
cl_assert(git_repository_head_detached(repo) == should_be_detached);
cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT));
cl_assert(git_repository_head_detached(repo) == should_be_detached);
cl_git_pass(git_reference_name_to_oid(&oid, repo, "HEAD"));
cl_git_pass(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO));
}
void test_reset_soft__can_reset_the_non_detached_Head_to_the_specified_commit(void)
{
assert_reset_soft(false);
}
static void detach_head(void)
{
git_reference *head;
git_oid oid;
cl_git_pass(git_reference_name_to_oid(&oid, repo, "HEAD"));
cl_git_pass(git_reference_create_oid(&head, repo, "HEAD", &oid, true));
git_reference_free(head);
}
void test_reset_soft__can_reset_the_detached_Head_to_the_specified_commit(void)
{
detach_head();
assert_reset_soft(true);
}
void test_reset_soft__resetting_to_the_commit_pointed_at_by_the_Head_does_not_change_the_target_of_the_Head(void)
{
git_oid oid;
char raw_head_oid[GIT_OID_HEXSZ + 1];
cl_git_pass(git_reference_name_to_oid(&oid, repo, "HEAD"));
git_oid_fmt(raw_head_oid, &oid);
raw_head_oid[GIT_OID_HEXSZ] = '\0';
retrieve_target_from_oid(&target, repo, raw_head_oid);
cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT));
cl_git_pass(git_reference_name_to_oid(&oid, repo, "HEAD"));
cl_git_pass(git_oid_streq(&oid, raw_head_oid));
}
void test_reset_soft__resetting_to_a_tag_sets_the_Head_to_the_peeled_commit(void)
{
git_oid oid;
/* b25fa35 is a tag, pointing to another tag which points to commit e90810b */
retrieve_target_from_oid(&target, repo, "b25fa35b38051e4ae45d4222e795f9df2e43f1d1");
cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT));
cl_assert(git_repository_head_detached(repo) == false);
cl_git_pass(git_reference_name_to_oid(&oid, repo, "HEAD"));
cl_git_pass(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO));
}
void test_reset_soft__cannot_reset_to_a_tag_not_pointing_at_a_commit(void)
{
/* 53fc32d is the tree of commit e90810b */
retrieve_target_from_oid(&target, repo, "53fc32d17276939fc79ed05badaef2db09990016");
cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT));
git_object_free(target);
/* 521d87c is an annotated tag pointing to a blob */
retrieve_target_from_oid(&target, repo, "521d87c1ec3aef9824daf6d96cc0ae3710766d91");
cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT));
}
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
Unnamed repository; edit this file 'description' to name the repository.
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
0000000000000000000000000000000000000000 9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a Russell Belfer <rb@github.com> 1338847682 -0700 commit (initial): Initial commit of test data
0000000000000000000000000000000000000000 9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a Russell Belfer <rb@github.com> 1338847682 -0700 commit (initial): Initial commit of test data
9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a
......@@ -6,3 +6,7 @@
[remote "test"]
url = git://github.com/libgit2/libgit2
fetch = +refs/heads/*:refs/remotes/test/*
[branch "master"]
remote = test
merge = refs/heads/master
0000000000000000000000000000000000000000 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub <bstraub@github.com> 1335806563 -0700 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git
be3563ae3f795b2b4353bcce3a527ad0a4f7f644 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub <bstraub@github.com> 1335806603 -0900 commit:
a65fedf39aefe402d3bb6e24df4d4f5fe4547750 c47800c7266a2be04c571c04d5a6614691ea99bd Ben Straub <bstraub@github.com> 1335806608 -0900 checkout: moving from master to br2
c47800c7266a2be04c571c04d5a6614691ea99bd a4a7dce85cf63874e984719f4fdd239f5145052f Ben Straub <bstraub@github.com> 1335806617 -0900 commit: checking in
a4a7dce85cf63874e984719f4fdd239f5145052f a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub <bstraub@github.com> 1335806621 -0900 checkout: moving from br2 to master
0000000000000000000000000000000000000000 c47800c7266a2be04c571c04d5a6614691ea99bd Ben Straub <bstraub@github.com> 1335806608 -0700 branch: Created from refs/remotes/origin/br2
a4a7dce85cf63874e984719f4fdd239f5145052f a4a7dce85cf63874e984719f4fdd239f5145052f Ben Straub <bstraub@github.com> 1335806617 -0700 commit: checking in
0000000000000000000000000000000000000000 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub <bstraub@github.com> 1335806563 -0800 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git
be3563ae3f795b2b4353bcce3a527ad0a4f7f644 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub <bstraub@github.com> 1335806603 -0800 commit: checking in
0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub <bstraub@github.com> 1336761944 -0700 branch: Created from master
0000000000000000000000000000000000000000 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub <bstraub@github.com> 1335806563 -0700 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git
a65fedf39aefe402d3bb6e24df4d4f5fe4547750
be3563ae3f795b2b4353bcce3a527ad0a4f7f644
849a5e34a26815e821f865b8479f5815a47af0fe
849a5e34a26815e821f865b8479f5815a47af0fe
......@@ -131,3 +131,17 @@ void test_status_ignore__empty_repo_with_gitignore_rewrite(void)
cl_assert(ignored);
}
void test_status_ignore__ignore_pattern_contains_space(void)
{
unsigned int flags;
const mode_t mode = 0777;
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_git_rewritefile("empty_standard_repo/.gitignore", "foo bar.txt\n");
cl_git_pass(git_futils_mkdir_r("empty_standard_repo/foo", NULL, mode));
cl_git_mkfile("empty_standard_repo/foo/look-ma.txt", "I'm not going to be ignored!");
cl_git_pass(git_status_file(&flags, g_repo, "foo/look-ma.txt"));
cl_assert(flags == GIT_STATUS_WT_NEW);
}
......@@ -581,3 +581,69 @@ void test_status_worktree__space_in_filename(void)
git_index_free(index);
git_repository_free(repo);
}
static const char *filemode_paths[] = {
"exec_off",
"exec_off2on_staged",
"exec_off2on_workdir",
"exec_off_untracked",
"exec_on",
"exec_on2off_staged",
"exec_on2off_workdir",
"exec_on_untracked",
};
static unsigned int filemode_statuses[] = {
GIT_STATUS_CURRENT,
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW,
GIT_STATUS_CURRENT,
GIT_STATUS_INDEX_MODIFIED,
GIT_STATUS_WT_MODIFIED,
GIT_STATUS_WT_NEW
};
static const size_t filemode_count = 8;
void test_status_worktree__filemode_changes(void)
{
git_repository *repo = cl_git_sandbox_init("filemodes");
status_entry_counts counts;
git_status_options opts;
git_config *cfg;
/* overwrite stored filemode with platform appropriate value */
cl_git_pass(git_repository_config(&cfg, repo));
if (cl_is_chmod_supported())
cl_git_pass(git_config_set_bool(cfg, "core.filemode", true));
else {
unsigned int i;
cl_git_pass(git_config_set_bool(cfg, "core.filemode", false));
/* won't trust filesystem mode diffs, so these will appear unchanged */
for (i = 0; i < filemode_count; ++i)
if (filemode_statuses[i] == GIT_STATUS_WT_MODIFIED)
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;
memset(&counts, 0, sizeof(counts));
counts.expected_entry_count = filemode_count;
counts.expected_paths = filemode_paths;
counts.expected_statuses = filemode_statuses;
cl_git_pass(
git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)
);
cl_assert_equal_i(counts.expected_entry_count, counts.entry_count);
cl_assert_equal_i(0, counts.wrong_status_flags_count);
cl_assert_equal_i(0, counts.wrong_sorted_path);
git_config_free(cfg);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment