summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt32
-rw-r--r--COPYING10
-rw-r--r--README.md2
-rw-r--r--deps/zlib/zconf.h3
-rw-r--r--examples/general.c24
-rw-r--r--include/git2/commit.h73
-rw-r--r--include/git2/config.h25
-rw-r--r--include/git2/errors.h5
-rw-r--r--include/git2/odb.h8
-rw-r--r--include/git2/oid.h15
-rw-r--r--include/git2/refs.h74
-rw-r--r--include/git2/repository.h32
-rw-r--r--include/git2/tag.h106
-rw-r--r--include/git2/tree.h2
-rw-r--r--include/git2/types.h2
-rw-r--r--src/blob.c33
-rw-r--r--src/commit.c90
-rw-r--r--src/common.h8
-rw-r--r--src/config.c16
-rw-r--r--src/config_file.c42
-rw-r--r--src/errors.c7
-rw-r--r--src/filebuf.c35
-rw-r--r--src/fileops.c588
-rw-r--r--src/fileops.h249
-rw-r--r--src/hash.c4
-rw-r--r--src/hashtable.c10
-rw-r--r--src/hashtable.h2
-rw-r--r--src/index.c20
-rw-r--r--src/map.h6
-rw-r--r--src/odb.c14
-rw-r--r--src/odb_loose.c30
-rw-r--r--src/odb_pack.c70
-rw-r--r--src/oid.c30
-rw-r--r--src/path.c254
-rw-r--r--src/path.h81
-rw-r--r--src/posix.c74
-rw-r--r--src/posix.h54
-rw-r--r--src/pqueue.c2
-rw-r--r--src/pqueue.h2
-rw-r--r--src/refs.c618
-rw-r--r--src/repository.c358
-rw-r--r--src/sha1.c (renamed from src/block-sha1/sha1.c)0
-rw-r--r--src/sha1.h (renamed from src/block-sha1/sha1.h)0
-rw-r--r--src/signature.c217
-rw-r--r--src/tag.c210
-rw-r--r--src/tree.c22
-rw-r--r--src/unix/map.c9
-rw-r--r--src/unix/posix.h14
-rw-r--r--src/util.c216
-rw-r--r--src/util.h56
-rw-r--r--src/vector.c2
-rw-r--r--src/win32/fileops.c41
-rw-r--r--src/win32/map.c4
-rw-r--r--src/win32/mingw-compat.h (renamed from src/mingw-compat.h)0
-rw-r--r--src/win32/msvc-compat.h (renamed from src/msvc-compat.h)0
-rw-r--r--src/win32/posix.c211
-rw-r--r--src/win32/posix.h26
-rw-r--r--tests/resources/config/config101
-rw-r--r--tests/resources/config/config91
-rw-r--r--tests/t00-core.c316
-rw-r--r--tests/t02-objread.c2
-rw-r--r--tests/t03-objwrite.c12
-rw-r--r--tests/t04-commit.c240
-rw-r--r--tests/t05-revwalk.c4
-rw-r--r--tests/t06-index.c6
-rw-r--r--tests/t08-tag.c58
-rw-r--r--tests/t10-refs.c112
-rw-r--r--tests/t12-repo.c107
-rw-r--r--tests/t15-config.c67
-rw-r--r--tests/test_helpers.c75
-rwxr-xr-xtests/test_lib.c30
-rwxr-xr-xtests/test_lib.h3
72 files changed, 2507 insertions, 2665 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 730fe4bb8..82208dc12 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@
# > mkdir build && cd build
# > cmake .. [-DSETTINGS=VALUE]
# > cmake --build .
-#
+#
# Testing:
# > ctest -V
#
@@ -22,7 +22,19 @@ STRING(REGEX REPLACE "^.*LIBGIT2_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1"
SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${LIBGIT2_VERSION_REV}")
# Find required dependencies
-INCLUDE_DIRECTORIES(deps/zlib src include)
+INCLUDE_DIRECTORIES(src include)
+IF (NOT WIN32)
+ FIND_PACKAGE(ZLIB)
+ENDIF()
+
+IF (ZLIB_FOUND)
+ INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
+ LINK_LIBRARIES(${ZLIB_LIBRARIES})
+ELSE (ZLIB_FOUND)
+ INCLUDE_DIRECTORIES(deps/zlib)
+ ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP)
+ FILE(GLOB SRC_ZLIB deps/zlib/*.c)
+ENDIF()
# Installation paths
SET(INSTALL_BIN bin CACHE PATH "Where to install binaries to.")
@@ -59,27 +71,27 @@ IF (THREADSAFE)
ADD_DEFINITIONS(-DGIT_THREADS)
ENDIF()
+ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
+
# Collect sourcefiles
-FILE(GLOB SRC src/*.c src/backends/*.c)
-FILE(GLOB SRC_ZLIB deps/zlib/*.c)
-FILE(GLOB SRC_SHA1 src/block-sha1/*.c)
-FILE(GLOB SRC_PLAT src/unix/*.c)
FILE(GLOB SRC_H include/git2/*.h)
# On Windows use specific platform sources
IF (WIN32 AND NOT CYGWIN)
ADD_DEFINITIONS(-DWIN32 -D_DEBUG -D_LIB)
- FILE(GLOB SRC_PLAT src/win32/*.c)
+ FILE(GLOB SRC src/*.c src/win32/*.c)
+ELSE()
+ FILE(GLOB SRC src/*.c src/unix/*.c)
ENDIF ()
# Compile and link libgit2
-ADD_LIBRARY(git2 ${SRC} ${SRC_PLAT} ${SRC_SHA1} ${SRC_ZLIB})
+ADD_LIBRARY(git2 ${SRC} ${SRC_ZLIB})
TARGET_LINK_LIBRARIES(git2 ${CMAKE_THREAD_LIBS_INIT})
SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING})
SET_TARGET_PROPERTIES(git2 PROPERTIES SOVERSION ${LIBGIT2_VERSION_MAJOR})
# Install
-INSTALL(TARGETS git2
+INSTALL(TARGETS git2
RUNTIME DESTINATION ${INSTALL_BIN}
LIBRARY DESTINATION ${INSTALL_LIB}
ARCHIVE DESTINATION ${INSTALL_LIB}
@@ -95,7 +107,7 @@ IF (BUILD_TESTS)
INCLUDE_DIRECTORIES(tests)
FILE(GLOB SRC_TEST tests/t??-*.c)
- ADD_EXECUTABLE(libgit2_test tests/test_main.c tests/test_lib.c tests/test_helpers.c ${SRC} ${SRC_PLAT} ${SRC_SHA1} ${SRC_TEST} ${SRC_ZLIB})
+ ADD_EXECUTABLE(libgit2_test tests/test_main.c tests/test_lib.c tests/test_helpers.c ${SRC} ${SRC_TEST} ${SRC_ZLIB})
TARGET_LINK_LIBRARIES(libgit2_test ${CMAKE_THREAD_LIBS_INIT})
ENABLE_TESTING()
diff --git a/COPYING b/COPYING
index c36f4cf1e..75bc6a1fe 100644
--- a/COPYING
+++ b/COPYING
@@ -71,7 +71,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
-
+
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -126,7 +126,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
-
+
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -184,7 +184,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
-
+
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -241,7 +241,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
-
+
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -294,7 +294,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
-
+
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
diff --git a/README.md b/README.md
index 825cf3e30..2c24da45e 100644
--- a/README.md
+++ b/README.md
@@ -101,7 +101,7 @@ GitHub, or join us on the mailing list by sending an email to:
libgit2@librelist.com
-License
+License
==================================
libgit2 is under GPL2 **with linking exemption**. This means you
can link to the library with any program, commercial, open source or
diff --git a/deps/zlib/zconf.h b/deps/zlib/zconf.h
index 494992aba..150814361 100644
--- a/deps/zlib/zconf.h
+++ b/deps/zlib/zconf.h
@@ -10,9 +10,6 @@
#include "../../src/common.h"
-#define NO_GZIP
-#define STDC
-
/* Jeez, don't complain about non-prototype
* forms, we didn't write zlib */
#if defined(_MSC_VER)
diff --git a/examples/general.c b/examples/general.c
index dbecbd206..f02c40977 100644
--- a/examples/general.c
+++ b/examples/general.c
@@ -1,7 +1,7 @@
// [**libgit2**][lg] is a portable, pure C implementation of the Git core methods
// provided as a re-entrant linkable library with a solid API, allowing you
-// to write native speed custom Git applications in any language which
-// supports C bindings.
+// to write native speed custom Git applications in any language which
+// supports C bindings.
//
// This file is an example of using that API in a real, compilable C file.
// As the API is updated, this file will be updated to demonstrate the
@@ -65,8 +65,8 @@ int main (int argc, char** argv)
// ### Working with the Object Database
// **libgit2** provides [direct access][odb] to the object database.
- // The object database is where the actual objects are stored in Git. For
- // working with raw objects, we'll need to get this structure from the
+ // The object database is where the actual objects are stored in Git. For
+ // working with raw objects, we'll need to get this structure from the
// repository.
// [odb]: http://libgit2.github.com/libgit2/#HEAD/group/odb
git_odb *odb;
@@ -94,10 +94,10 @@ int main (int argc, char** argv)
data = (const unsigned char *)git_odb_object_data(obj);
otype = git_odb_object_type(obj);
- // We provide methods to convert from the object type which is an enum, to a string
+ // We provide methods to convert from the object type which is an enum, to a string
// representation of that value (and vice-versa).
str_type = git_object_type2string(otype);
- printf("object length and type: %d, %s\n",
+ printf("object length and type: %d, %s\n",
(int)git_odb_object_size(obj),
str_type);
@@ -126,7 +126,7 @@ int main (int argc, char** argv)
// yourself.
// #### Commit Parsing
- // [Parsing commit objects][pco] is simple and gives you access to all the data in the commit
+ // [Parsing commit objects][pco] is simple and gives you access to all the data in the commit
// - the // author (name, email, datetime), committer (same), tree, message, encoding and parent(s).
// [pco]: http://libgit2.github.com/libgit2/#HEAD/group/commit
@@ -156,7 +156,7 @@ int main (int argc, char** argv)
printf("Author: %s (%s)\n", author->name, author->email);
// Commits can have zero or more parents. The first (root) commit will have no parents, most commits
- // will have one, which is the commit it was based on, and merge commits will have two or more.
+ // will have one, which is the commit it was based on, and merge commits will have two or more.
// Commits can technically have any number, though it's pretty rare to have more than two.
parents = git_commit_parentcount(commit);
for (p = 0;p < parents;p++) {
@@ -191,7 +191,7 @@ int main (int argc, char** argv)
987654321, 90);
// Commit objects need a tree to point to and optionally one or more parents. Here we're creating oid
- // objects to create the commit with, but you can also use
+ // objects to create the commit with, but you can also use
git_oid_fromstr(&tree_id, "28873d96b4e8f4e33ea30f4c682fd325f7ba56ac");
git_oid_fromstr(&parent_id, "f0877d0b841d75172ec404fc9370173dfffc20d1");
@@ -227,7 +227,7 @@ int main (int argc, char** argv)
error = git_tag_lookup(&tag, repo, &oid);
// Now that we have the tag object, we can extract the information it generally contains: the target
- // (usually a commit object), the type of the target object (usually 'commit'), the name ('v1.0'),
+ // (usually a commit object), the type of the target object (usually 'commit'), the name ('v1.0'),
// the tagger (a git_signature - name, email, timestamp), and the tag message.
git_tag_target((git_object **)&commit, tag);
tname = git_tag_name(tag); // "test"
@@ -275,7 +275,7 @@ int main (int argc, char** argv)
//
// The last object type is the simplest and requires the least parsing help. Blobs are just file
// contents and can contain anything, there is no structure to it. The main advantage to using the
- // [simple blob api][ba] is that when you're creating blobs you don't have to calculate the size
+ // [simple blob api][ba] is that when you're creating blobs you don't have to calculate the size
// of the content. There is also a helper for reading a file from disk and writing it to the db and
// getting the oid back so you don't have to do all those steps yourself.
//
@@ -343,7 +343,7 @@ int main (int argc, char** argv)
// ### Index File Manipulation
//
- // The [index file API][gi] allows you to read, traverse, update and write the Git index file
+ // The [index file API][gi] allows you to read, traverse, update and write the Git index file
// (sometimes thought of as the staging area).
//
// [gi]: http://libgit2.github.com/libgit2/#HEAD/group/index
diff --git a/include/git2/commit.h b/include/git2/commit.h
index 356b875cd..84adef596 100644
--- a/include/git2/commit.h
+++ b/include/git2/commit.h
@@ -193,7 +193,8 @@ GIT_EXTERN(int) git_commit_parent(git_commit **parent, git_commit *commit, unsig
GIT_EXTERN(const git_oid *) git_commit_parent_oid(git_commit *commit, unsigned int n);
/**
- * Create a new commit in the repository
+ * Create a new commit in the repository using `git_object`
+ * instances as parameters.
*
* @param oid Pointer where to store the OID of the
* newly created commit
@@ -214,16 +215,16 @@ GIT_EXTERN(const git_oid *) git_commit_parent_oid(git_commit *commit, unsigned i
*
* @param message Full message for this commit
*
- * @param tree_oid Object ID of the tree for this commit. Note that
- * no validation is performed on this OID. Use the _o variants of
- * this method to assure a proper tree is passed to the commit.
+ * @param tree An instance of a `git_tree` object that will
+ * be used as the tree for the commit. This tree object must
+ * also be owned by the given `repo`.
*
* @param parent_count Number of parents for this commit
*
- * @param parent_oids[] Array of pointers to parent OIDs for this commit.
- * Note that no validation is performed on these OIDs. Use the _o
- * variants of this method to assure that are parents for the commit
- * are proper objects.
+ * @param parents[] Array of `parent_count` pointers to `git_commit`
+ * objects that will be used as the parents for this commit. This
+ * array may be NULL if `parent_count` is 0 (root commit). All the
+ * given commits must be owned by the `repo`.
*
* @return 0 on success; error code otherwise
* The created commit will be written to the Object Database and
@@ -236,38 +237,13 @@ GIT_EXTERN(int) git_commit_create(
const git_signature *author,
const git_signature *committer,
const char *message,
- const git_oid *tree_oid,
- int parent_count,
- const git_oid *parent_oids[]);
-
-/**
- * Create a new commit in the repository using `git_object`
- * instances as parameters.
- *
- * The `tree_oid` and `parent_oids` paremeters now take a instance
- * of `git_tree` and `git_commit`, respectively.
- *
- * All other parameters remain the same
- *
- * @see git_commit_create
- */
-GIT_EXTERN(int) git_commit_create_o(
- git_oid *oid,
- git_repository *repo,
- const char *update_ref,
- const git_signature *author,
- const git_signature *committer,
- const char *message,
const git_tree *tree,
int parent_count,
const git_commit *parents[]);
/**
- * Create a new commit in the repository using `git_object`
- * instances and a variable argument list.
- *
- * The `tree_oid` paremeter now takes a instance
- * of `const git_tree *`.
+ * Create a new commit in the repository using a variable
+ * argument list.
*
* The parents for the commit are specified as a variable
* list of pointers to `const git_commit *`. Note that this
@@ -278,31 +254,6 @@ GIT_EXTERN(int) git_commit_create_o(
*
* @see git_commit_create
*/
-GIT_EXTERN(int) git_commit_create_ov(
- git_oid *oid,
- git_repository *repo,
- const char *update_ref,
- const git_signature *author,
- const git_signature *committer,
- const char *message,
- const git_tree *tree,
- int parent_count,
- ...);
-
-
-/**
- * Create a new commit in the repository using
- * a variable argument list.
- *
- * The parents for the commit are specified as a variable
- * list of pointers to `const git_oid *`. Note that this
- * is a convenience method which may not be safe to export
- * for certain languages or compilers
- *
- * All other parameters remain the same
- *
- * @see git_commit_create
- */
GIT_EXTERN(int) git_commit_create_v(
git_oid *oid,
git_repository *repo,
@@ -310,7 +261,7 @@ GIT_EXTERN(int) git_commit_create_v(
const git_signature *author,
const git_signature *committer,
const char *message,
- const git_oid *tree_oid,
+ const git_tree *tree,
int parent_count,
...);
diff --git a/include/git2/config.h b/include/git2/config.h
index feac112b1..a8bff6cf0 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -48,7 +48,7 @@ struct git_config_file {
int (*open)(struct git_config_file *);
int (*get)(struct git_config_file *, const char *key, const char **value);
int (*set)(struct git_config_file *, const char *key, const char *value);
- int (*foreach)(struct git_config_file *, int (*fn)(const char *, void *), void *data);
+ int (*foreach)(struct git_config_file *, int (*fn)(const char *, const char *, void *), void *data);
void (*free)(struct git_config_file *);
};
@@ -254,19 +254,30 @@ GIT_EXTERN(int) git_config_set_bool(git_config *cfg, const char *name, int value
GIT_EXTERN(int) git_config_set_string(git_config *cfg, const char *name, const char *value);
/**
+ * Delete a config variable
+ *
+ * @param cfg the configuration
+ * @param name the variable to delete
+ */
+GIT_EXTERN(int) git_config_del(git_config *cfg, const char *name);
+
+/**
* Perform an operation on each config variable.
*
- * The callback is passed a pointer to a config variable name and the
- * data pointer passed to this function. As soon as one of the
- * callback functions returns something other than 0, this function
- * returns that value.
+ * The callback receives the normalized name and value of each variable
+ * in the config backend, and the data pointer passed to this function.
+ * As soon as one of the callback functions returns something other than 0,
+ * this function returns that value.
*
* @param cfg where to get the variables from
* @param callback the function to call on each variable
- * @param data the data to pass to the callback
+ * @param payload the data to pass to the callback
* @return GIT_SUCCESS or the return value of the callback which didn't return 0
*/
-GIT_EXTERN(int) git_config_foreach(git_config *cfg, int (*callback)(const char *, void *data), void *data);
+GIT_EXTERN(int) git_config_foreach(
+ git_config *cfg,
+ int (*callback)(const char *var_name, const char *value, void *payload),
+ void *payload);
/** @} */
GIT_END_DECL
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 03c74e822..710ac244b 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -152,6 +152,11 @@ GIT_EXTERN(const char *) git_lasterror(void);
*/
GIT_EXTERN(const char *) git_strerror(int num);
+/**
+ * Clear the latest library error
+ */
+GIT_EXTERN(void) git_clearerror(void);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/odb.h b/include/git2/odb.h
index 06b9aa5f1..ef16e1e42 100644
--- a/include/git2/odb.h
+++ b/include/git2/odb.h
@@ -91,7 +91,7 @@ GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int
* backend will work as an alternate.
*
* Alternate backends are always checked for objects *after*
- * all the main backends have been exhausted.
+ * all the main backends have been exhausted.
*
* The backends are checked in relative ordering, based on the
* value of the `priority` parameter.
@@ -220,12 +220,12 @@ GIT_EXTERN(int) git_odb_write(git_oid *oid, git_odb *odb, const void *data, size
*
* The returned stream will be of type `GIT_STREAM_WRONLY` and
* will have the following methods:
- *
+ *
* - stream->write: write `n` bytes into the stream
* - stream->finalize_write: close the stream and store the object in
* the odb
* - stream->free: free the stream
- *
+ *
* The streaming write won't be effective until `stream->finalize_write`
* is called and returns without an error
*
@@ -252,7 +252,7 @@ GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **stream, git_odb *db, size_
*
* The returned stream will be of type `GIT_STREAM_RDONLY` and
* will have the following methods:
- *
+ *
* - stream->read: read `n` bytes from the stream
* - stream->free: free the stream
*
diff --git a/include/git2/oid.h b/include/git2/oid.h
index 06bbfcc55..96f8649f0 100644
--- a/include/git2/oid.h
+++ b/include/git2/oid.h
@@ -65,6 +65,19 @@ typedef struct {
GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str);
/**
+ * Parse N characters of a hex formatted object id into a git_oid
+ *
+ * If N is odd, N-1 characters will be parsed instead.
+ * The remaining space in the git_oid will be set to zero.
+ *
+ * @param out oid structure the result is written into.
+ * @param str input hex string of at least size `length`
+ * @param length length of the input string
+ * @return GIT_SUCCESS if valid; GIT_ENOTOID on failure.
+ */
+GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length);
+
+/**
* Copy an already raw oid into a git_oid structure.
*
* @param out oid structure the result is written into.
@@ -202,7 +215,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid);
/**
* Free an OID shortener instance
- *
+ *
* @param os a `git_oid_shorten` instance
*/
void git_oid_shorten_free(git_oid_shorten *os);
diff --git a/include/git2/refs.h b/include/git2/refs.h
index 2c3aac7b0..ff2bc9d87 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -60,34 +60,17 @@ GIT_EXTERN(int) git_reference_lookup(git_reference **reference_out, git_reposito
* This reference is owned by the repository and shall not
* be free'd by the user.
*
- * @param ref_out Pointer to the newly created reference
- * @param repo Repository where that reference will live
- * @param name The name of the reference
- * @param target The target of the reference
- * @return 0 on success; error code otherwise
- */
-GIT_EXTERN(int) git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target);
-
-/**
- * Create a new symbolic reference, overwriting an existing one with
- * the same name, if it exists.
- *
- * If the new reference isn't a symbolic one, any pointers to the old
- * reference become invalid.
- *
- * The reference will be created in the repository and written
- * to the disk.
- *
- * This reference is owned by the repository and shall not
- * be free'd by the user.
+ * If `force` is true and there already exists a reference
+ * with the same name, it will be overwritten.
*
* @param ref_out Pointer to the newly created reference
* @param repo Repository where that reference will live
* @param name The name of the reference
* @param target The target of the reference
+ * @param force Overwrite existing references
* @return 0 on success; error code otherwise
*/
-GIT_EXTERN(int) git_reference_create_symbolic_f(git_reference **ref_out, git_repository *repo, const char *name, const char *target);
+GIT_EXTERN(int) git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target, int force);
/**
* Create a new object id reference.
@@ -98,38 +81,21 @@ GIT_EXTERN(int) git_reference_create_symbolic_f(git_reference **ref_out, git_rep
* This reference is owned by the repository and shall not
* be free'd by the user.
*
- * @param ref_out Pointer to the newly created reference
- * @param repo Repository where that reference will live
- * @param name The name of the reference
- * @param id The object id pointed to by the reference.
- * @return 0 on success; error code otherwise
- */
-GIT_EXTERN(int) git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id);
-
-/**
- * Create a new object id reference, overwriting an existing one with
- * the same name, if it exists.
- *
- * If the new reference isn't an object id one, any pointers to the
- * old reference become invalid.
- *
- * The reference will be created in the repository and written
- * to the disk.
- *
- * This reference is owned by the repository and shall not
- * be free'd by the user.
+ * If `force` is true and there already exists a reference
+ * with the same name, it will be overwritten.
*
* @param ref_out Pointer to the newly created reference
* @param repo Repository where that reference will live
* @param name The name of the reference
* @param id The object id pointed to by the reference.
+ * @param force Overwrite existing references
* @return 0 on success; error code otherwise
*/
-GIT_EXTERN(int) git_reference_create_oid_f(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id);
+GIT_EXTERN(int) git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id, int force);
/**
* Get the OID pointed to by a reference.
- *
+ *
* Only available if the reference is direct (i.e. not symbolic)
*
* @param ref The reference
@@ -139,7 +105,7 @@ GIT_EXTERN(const git_oid *) git_reference_oid(git_reference *ref);
/**
* Get full name to the reference pointed by this reference
- *
+ *
* Only available if the reference is symbolic
*
* @param ref The reference
@@ -166,7 +132,7 @@ GIT_EXTERN(git_rtype) git_reference_type(git_reference *ref);
GIT_EXTERN(const char *) git_reference_name(git_reference *ref);
/**
- * Resolve a symbolic reference
+ * Resolve a symbolic reference
*
* Thie method iteratively peels a symbolic reference
* until it resolves to a direct reference to an OID.
@@ -229,21 +195,7 @@ GIT_EXTERN(int) git_reference_set_oid(git_reference *ref, const git_oid *id);
* and on disk.
*
*/
-GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name);
-
-/**
- * Rename an existing reference, overwriting an existing one with the
- * same name, if it exists.
- *
- * 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 refernece will be immediately renamed in-memory
- * and on disk.
- *
- */
-GIT_EXTERN(int) git_reference_rename_f(git_reference *ref, const char *new_name);
+GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name, int force);
/**
* Delete an existing reference
@@ -260,7 +212,7 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref);
* Pack all the loose references in the repository
*
* This method will load into the cache all the loose
- * references on the repository and update the
+ * references on the repository and update the
* `packed-refs` file with them.
*
* Once the `packed-refs` file has been written properly,
diff --git a/include/git2/repository.h b/include/git2/repository.h
index 27c3138f7..4088ff7f9 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -71,7 +71,7 @@ GIT_EXTERN(int) git_repository_open(git_repository **repository, const char *pat
*
* @param git_dir The full path to the repository folder
* e.g. a '.git' folder for live repos, any folder for bare
- * Equivalent to $GIT_DIR.
+ * Equivalent to $GIT_DIR.
* Cannot be NULL.
*
* @param git_object_directory The full path to the ODB folder.
@@ -105,7 +105,7 @@ GIT_EXTERN(int) git_repository_open2(git_repository **repository,
*
* @param git_dir The full path to the repository folder
* e.g. a '.git' folder for live repos, any folder for bare
- * Equivalent to $GIT_DIR.
+ * Equivalent to $GIT_DIR.
* Cannot be NULL.
*
* @param object_database A pointer to a git_odb created & initialized
@@ -210,8 +210,8 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo);
*
* @param repo_out pointer to the repo which will be created or reinitialized
* @param path the path to the repository
- * @param is_bare if true, a Git repository without a working directory is created
- * at the pointed path. If false, provided path will be considered as the working
+ * @param is_bare if true, a Git repository without a working directory is created
+ * at the pointed path. If false, provided path will be considered as the working
* directory into which the .git directory will be created.
*
* @return 0 on success; error code otherwise
@@ -219,6 +219,30 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo);
GIT_EXTERN(int) git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare);
/**
+ * Check if a repository's HEAD is detached
+ *
+ * A repository's HEAD is detached when it points directly to a commit
+ * instead of a branch.
+ *
+ * @param repo Repo to test
+ * @return 1 if HEAD is detached, 0 if i'ts not; error code if there
+ * was an error.
+ */
+GIT_EXTERN(int) git_repository_head_detached(git_repository *repo);
+
+/**
+ * Check if the current branch is an orphan
+ *
+ * An orphan branch is one named from HEAD but which doesn't exist in
+ * the refs namespace, because it doesn't have any commit to point to.
+ *
+ * @param repo Repo to test
+ * @return 1 if the current branch is an orphan, 0 if it's not; error
+ * code if therewas an error
+ */
+GIT_EXTERN(int) git_repository_head_orphan(git_repository *repo);
+
+/**
* Check if a repository is empty
*
* An empty repository has just been initialized and contains
diff --git a/include/git2/tag.h b/include/git2/tag.h
index b92f79d22..15635cce2 100644
--- a/include/git2/tag.h
+++ b/include/git2/tag.h
@@ -151,6 +151,10 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *tag);
/**
* Create a new tag in the repository from an OID
*
+ * A new reference will also be created pointing to
+ * this tag object. If `force` is true and a reference
+ * already exists with the given name, it'll be replaced.
+ *
* @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 existed tag, and the function will
@@ -159,21 +163,19 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *tag);
* @param repo Repository where to store the tag
*
* @param tag_name Name for the tag; this name is validated
- * for consistency. It should also not conflict with an
+ * for consistency. It should also not conflict with an
* already existing tag name
*
- * @param target OID to which this tag points; note that no
- * validation is done on this OID. Use the _o version of this
- * method to assure a proper object is being tagged
- *
- * @param target_type Type of the tagged OID; note that no
- * validation is performed here either
+ * @param target Object to which this tag points. This object
+ * must belong to the given `repo`.
*
* @param tagger Signature of the tagger for this tag, and
* of the tagging time
*
* @param message Full message for this tag
*
+ * @param force Overwritte existing references
+ *
* @return 0 on success; error code otherwise.
* A tag object is written to the ODB, and a proper reference
* is written in the /refs/tags folder, pointing to it
@@ -182,103 +184,25 @@ GIT_EXTERN(int) git_tag_create(
git_oid *oid,
git_repository *repo,
const char *tag_name,
- const git_oid *target,
- git_otype target_type,
- const git_signature *tagger,
- const char *message);
-
-
-/**
- * Create a new tag in the repository from an existing
- * `git_object` instance
- *
- * This method replaces the `target` and `target_type`
- * paremeters of `git_tag_create` by a single instance
- * of a `const git_object *`, which is assured to be
- * a proper object in the ODB and hence will create
- * a valid tag
- *
- * @see git_tag_create
- */
-GIT_EXTERN(int) git_tag_create_o(
- git_oid *oid,
- git_repository *repo,
- const char *tag_name,
const git_object *target,
const git_signature *tagger,
- const char *message);
+ const char *message,
+ int force);
/**
* Create a new tag in the repository from a buffer
*
* @param oid Pointer where to store the OID of the newly created tag
- *
* @param repo Repository where to store the tag
- *
* @param buffer Raw tag data
+ * @param force Overwrite existing tags
+ * @return 0 on sucess; error code otherwise
*/
GIT_EXTERN(int) git_tag_create_frombuffer(
git_oid *oid,
git_repository *repo,
- const char *buffer);
-
-/**
- * Create a new tag in the repository from an OID
- * and overwrite an already existing tag reference, if any.
- *
- * @param oid Pointer where to store the OID of the
- * newly created tag
- *
- * @param repo Repository where to store the tag
- *
- * @param tag_name Name for the tag; this name is validated
- * for consistency.
- *
- * @param target OID to which this tag points; note that no
- * validation is done on this OID. Use the _fo version of this
- * method to assure a proper object is being tagged
- *
- * @param target_type Type of the tagged OID; note that no
- * validation is performed here either
- *
- * @param tagger Signature of the tagger for this tag, and
- * of the tagging time
- *
- * @param message Full message for this tag
- *
- * @return 0 on success; error code otherwise.
- * A tag object is written to the ODB, and a proper reference
- * is written in the /refs/tags folder, pointing to it
- */
-GIT_EXTERN(int) git_tag_create_f(
- git_oid *oid,
- git_repository *repo,
- const char *tag_name,
- const git_oid *target,
- git_otype target_type,
- const git_signature *tagger,
- const char *message);
-
-/**
- * Create a new tag in the repository from an existing
- * `git_object` instance and overwrite an already existing
- * tag reference, if any.
- *
- * This method replaces the `target` and `target_type`
- * paremeters of `git_tag_create_f` by a single instance
- * of a `const git_object *`, which is assured to be
- * a proper object in the ODB and hence will create
- * a valid tag
- *
- * @see git_tag_create_f
- */
-GIT_EXTERN(int) git_tag_create_fo(
- git_oid *oid,
- git_repository *repo,
- const char *tag_name,
- const git_object *target,
- const git_signature *tagger,
- const char *message);
+ const char *buffer,
+ int force);
/**
* Delete an existing tag reference.
diff --git a/include/git2/tree.h b/include/git2/tree.h
index 80b90604f..5656f48f3 100644
--- a/include/git2/tree.h
+++ b/include/git2/tree.h
@@ -190,7 +190,7 @@ GIT_EXTERN(int) git_tree_create_fromindex(git_oid *oid, git_index *index);
*
* If the `source` parameter is not NULL, the tree builder
* will be initialized with the entries of the given tree.
- *
+ *
* If the `source` parameter is NULL, the tree builder will
* have no entries and will have to be filled manually.
*
diff --git a/include/git2/types.h b/include/git2/types.h
index dae96cf22..bc1b8a6c7 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -66,7 +66,7 @@ typedef __haiku_std_int64 git_time_t;
#else /* POSIX */
-/*
+/*
* Note: Can't use off_t since if a client program includes <sys/types.h>
* before us (directly or indirectly), they'll get 32 bit off_t in their client
* app, even though /we/ define _FILE_OFFSET_BITS=64.
diff --git a/src/blob.c b/src/blob.c
index d18aa5c36..b8282e505 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -91,31 +91,23 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
if (repo->path_workdir == NULL)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. (No working directory found)");
- git__joinpath(full_path, repo->path_workdir, path);
+ git_path_join(full_path, repo->path_workdir, path);
- error = gitfo_lstat(full_path, &st);
+ error = p_lstat(full_path, &st);
if (error < 0) {
return git__throw(GIT_EOSERR, "Failed to stat blob. %s", strerror(errno));
}
islnk = S_ISLNK(st.st_mode);
+ size = st.st_size;
-
- if (!islnk) {
- if ((fd = gitfo_open(full_path, O_RDONLY)) < 0)
+ if (!islnk)
+ if ((fd = p_open(full_path, O_RDONLY)) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. Could not open '%s'", full_path);
- if ((size = gitfo_size(fd)) < 0 || !git__is_sizet(size)) {
- gitfo_close(fd);
- return git__throw(GIT_EOSERR, "Failed to create blob. '%s' appears to be corrupted", full_path);
- }
- } else {
- size = st.st_size;
- }
-
if ((error = git_odb_open_wstream(&stream, repo->db, (size_t)size, GIT_OBJ_BLOB)) < GIT_SUCCESS) {
if (!islnk)
- gitfo_close(fd);
+ p_close(fd);
return git__rethrow(error, "Failed to create blob");
}
@@ -123,13 +115,13 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
ssize_t read_len;
if (!islnk)
- read_len = gitfo_read(fd, buffer, (size_t)(size < sizeof(buffer) ? size : sizeof(buffer)));
+ read_len = p_read(fd, buffer, sizeof(buffer));
else
- read_len = gitfo_readlink(full_path, buffer, (size_t)size);
+ read_len = p_readlink(full_path, buffer, sizeof(buffer));
if (read_len < 0) {
if (!islnk)
- gitfo_close(fd);
+ p_close(fd);
stream->free(stream);
return git__throw(GIT_EOSERR, "Failed to create blob. Can't read full file");
}
@@ -141,11 +133,8 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
error = stream->finalize_write(oid, stream);
stream->free(stream);
if (!islnk)
- gitfo_close(fd);
+ p_close(fd);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to create blob");
-
- return GIT_SUCCESS;
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create blob");
}
diff --git a/src/commit.c b/src/commit.c
index 6857eddab..c94ea7618 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -74,7 +74,6 @@ const git_oid *git_commit_id(git_commit *c)
return git_object_id((git_object *)c);
}
-
int git_commit_create_v(
git_oid *oid,
git_repository *repo,
@@ -82,63 +81,31 @@ int git_commit_create_v(
const git_signature *author,
const git_signature *committer,
const char *message,
- const git_oid *tree_oid,
- int parent_count,
- ...)
-{
- va_list ap;
- int i, error;
- const git_oid **oids;
-
- oids = git__malloc(parent_count * sizeof(git_oid *));
-
- va_start(ap, parent_count);
- for (i = 0; i < parent_count; ++i)
- oids[i] = va_arg(ap, const git_oid *);
- va_end(ap);
-
- error = git_commit_create(
- oid, repo, update_ref, author, committer, message,
- tree_oid, parent_count, oids);
-
- free((void *)oids);
-
- return error;
-}
-
-int git_commit_create_ov(
- git_oid *oid,
- git_repository *repo,
- const char *update_ref,
- const git_signature *author,
- const git_signature *committer,
- const char *message,
const git_tree *tree,
int parent_count,
...)
{
va_list ap;
int i, error;
- const git_oid **oids;
+ const git_commit **parents;
- oids = git__malloc(parent_count * sizeof(git_oid *));
+ parents = git__malloc(parent_count * sizeof(git_commit *));
va_start(ap, parent_count);
for (i = 0; i < parent_count; ++i)
- oids[i] = git_object_id(va_arg(ap, const git_object *));
+ parents[i] = va_arg(ap, const git_commit *);
va_end(ap);
error = git_commit_create(
oid, repo, update_ref, author, committer, message,
- git_object_id((git_object *)tree),
- parent_count, oids);
+ tree, parent_count, parents);
- free((void *)oids);
+ free((void *)parents);
return error;
}
-int git_commit_create_o(
+int git_commit_create(
git_oid *oid,
git_repository *repo,
const char *update_ref,
@@ -149,35 +116,6 @@ int git_commit_create_o(
int parent_count,
const git_commit *parents[])
{
- int i, error;
- const git_oid **oids;
-
- oids = git__malloc(parent_count * sizeof(git_oid *));
-
- for (i = 0; i < parent_count; ++i)
- oids[i] = git_object_id((git_object *)parents[i]);
-
- error = git_commit_create(
- oid, repo, update_ref, author, committer, message,
- git_object_id((git_object *)tree),
- parent_count, oids);
-
- free((void *)oids);
-
- return error;
-}
-
-int git_commit_create(
- git_oid *oid,
- git_repository *repo,
- const char *update_ref,
- const git_signature *author,
- const git_signature *committer,
- const char *message,
- const git_oid *tree_oid,
- int parent_count,
- const git_oid *parents[])
-{
size_t final_size = 0;
int message_length, author_length, committer_length;
@@ -202,10 +140,17 @@ int git_commit_create(
if ((error = git_odb_open_wstream(&stream, repo->db, final_size, GIT_OBJ_COMMIT)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create commit");
- git__write_oid(stream, "tree", tree_oid);
+ if (git_object_owner((const git_object *)tree) != repo)
+ return git__throw(GIT_EINVALIDARGS, "The given tree does not belong to this repository");
- for (i = 0; i < parent_count; ++i)
- git__write_oid(stream, "parent", parents[i]);
+ git__write_oid(stream, "tree", git_object_id((const git_object *)tree));
+
+ for (i = 0; i < parent_count; ++i) {
+ if (git_object_owner((const git_object *)parents[i]) != repo)
+ return git__throw(GIT_EINVALIDARGS, "The given parent does not belong to this repository");
+
+ git__write_oid(stream, "parent", git_object_id((const git_object *)parents[i]));
+ }
stream->write(stream, author_str, author_length);
free(author_str);
@@ -213,7 +158,6 @@ int git_commit_create(
stream->write(stream, committer_str, committer_length);
free(committer_str);
-
stream->write(stream, "\n", 1);
stream->write(stream, message, message_length);
@@ -238,7 +182,7 @@ int git_commit_create(
* point to) or after an orphan checkout, so if the target
* branch doesn't exist yet, create it and return.
*/
- return git_reference_create_oid_f(&head, repo, git_reference_target(head), oid);
+ return git_reference_create_oid(&head, repo, git_reference_target(head), oid, 1);
}
error = git_reference_set_oid(head, oid);
diff --git a/src/common.h b/src/common.h
index b6a6b4d5c..e1e7f0035 100644
--- a/src/common.h
+++ b/src/common.h
@@ -2,10 +2,6 @@
#define INCLUDE_common_h__
#include "git2/common.h"
-
-/** Force 64 bit off_t size on POSIX. */
-#define _FILE_OFFSET_BITS 64
-
#include "git2/thread-utils.h"
#include "cc-compat.h"
@@ -27,8 +23,8 @@
# include <io.h>
# include <direct.h>
# include <windows.h>
-# include "msvc-compat.h"
-# include "mingw-compat.h"
+# include "win32/msvc-compat.h"
+# include "win32/mingw-compat.h"
# ifdef GIT_THREADS
# include "win32/pthread.h"
#endif
diff --git a/src/config.c b/src/config.c
index cc31bda6d..730917634 100644
--- a/src/config.c
+++ b/src/config.c
@@ -127,7 +127,7 @@ int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
assert(cfg && file);
if ((error = file->open(file)) < GIT_SUCCESS)
- return git__throw(error, "Failed to open config file");
+ return git__rethrow(error, "Failed to open config file");
internal = git__malloc(sizeof(file_internal));
if (internal == NULL)
@@ -151,7 +151,7 @@ int git_config_add_file(git_config *cfg, git_config_file *file, int priority)
* Loop over all the variables
*/
-int git_config_foreach(git_config *cfg, int (*fn)(const char *, void *), void *data)
+int git_config_foreach(git_config *cfg, int (*fn)(const char *, const char *, void *), void *data)
{
int ret = GIT_SUCCESS;
unsigned int i;
@@ -167,15 +167,15 @@ int git_config_foreach(git_config *cfg, int (*fn)(const char *, void *), void *d
return ret;
}
+int git_config_del(git_config *cfg, const char *name)
+{
+ return git_config_set_string(cfg, name, NULL);
+}
/**************
* Setters
**************/
-/*
- * Internal function to actually set the string value of a variable
- */
-
int git_config_set_long(git_config *cfg, const char *name, long int value)
{
char str_value[32]; /* All numbers should fit in here */
@@ -333,9 +333,9 @@ int git_config_find_global(char *global_config_path)
if (home == NULL)
return git__throw(GIT_EOSERR, "Failed to open global config file. Cannot locate the user's home directory");
- git__joinpath(global_config_path, home, GIT_CONFIG_FILENAME);
+ git_path_join(global_config_path, home, GIT_CONFIG_FILENAME);
- if (gitfo_exists(global_config_path) < GIT_SUCCESS)
+ if (git_futils_exists(global_config_path) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to open global config file. The file does not exist");
return GIT_SUCCESS;
diff --git a/src/config_file.c b/src/config_file.c
index 2966f11bd..044a24310 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -89,7 +89,7 @@ typedef struct {
cvar_t_list var_list;
struct {
- gitfo_buf buffer;
+ git_fbuffer buffer;
char *read_ptr;
int line_number;
int eof;
@@ -278,7 +278,7 @@ static int config_open(git_config_file *cfg)
int error;
diskfile_backend *b = (diskfile_backend *)cfg;
- error = gitfo_read_file(&b->reader.buffer, b->file_path);
+ error = git_futils_readbuffer(&b->reader.buffer, b->file_path);
if(error < GIT_SUCCESS)
goto cleanup;
@@ -286,13 +286,13 @@ static int config_open(git_config_file *cfg)
if (error < GIT_SUCCESS)
goto cleanup;
- gitfo_free_buf(&b->reader.buffer);
+ git_futils_freebuffer(&b->reader.buffer);
return error;
cleanup:
cvar_list_free(&b->var_list);
- gitfo_free_buf(&b->reader.buffer);
+ git_futils_freebuffer(&b->reader.buffer);
return git__rethrow(error, "Failed to open config");
}
@@ -310,7 +310,7 @@ static void backend_free(git_config_file *_backend)
free(backend);
}
-static int file_foreach(git_config_file *backend, int (*fn)(const char *, void *), void *data)
+static int file_foreach(git_config_file *backend, int (*fn)(const char *, const char *, void *), void *data)
{
int ret = GIT_SUCCESS;
cvar_t *var;
@@ -323,7 +323,7 @@ static int file_foreach(git_config_file *backend, int (*fn)(const char *, void *
if (ret < GIT_SUCCESS)
return ret;
- ret = fn(normalized, data);
+ ret = fn(normalized, var->value, data);
free(normalized);
if (ret)
break;
@@ -356,9 +356,14 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
}
/*
- * Otherwise, create it and stick it at the end of the queue.
+ * Otherwise, create it and stick it at the end of the queue. If
+ * value is NULL, we return an error, because you can't delete a
+ * variable that doesn't exist.
*/
+ if (value == NULL)
+ return git__throw(GIT_ENOTFOUND, "Can't delete non-exitent variable");
+
last_dot = strrchr(name, '.');
if (last_dot == NULL) {
return git__throw(GIT_EINVALIDTYPE, "Variables without section aren't allowed");
@@ -716,11 +721,6 @@ static int parse_section_header(diskfile_backend *cfg, char **section_out)
c = line[pos++];
do {
- if (cfg->reader.eof){
- error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse header. Config file ended unexpectedly");
- goto error;
- }
-
if (isspace(c)){
name[name_length] = '\0';
error = parse_section_header_ext(line, name, section_out);
@@ -738,6 +738,9 @@ static int parse_section_header(diskfile_backend *cfg, char **section_out)
} while ((c = line[pos++]) != ']');
+ if (line[pos - 1] != ']')
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse header. Config file ended unexpectedly");
+
name[name_length] = 0;
free(line);
git__strtolower(name);
@@ -921,7 +924,7 @@ static int config_write(diskfile_backend *cfg, cvar_t *var)
const char *pre_end = NULL, *post_start = NULL;
/* We need to read in our own config file */
- error = gitfo_read_file(&cfg->reader.buffer, cfg->file_path);
+ error = git_futils_readbuffer(&cfg->reader.buffer, cfg->file_path);
if (error < GIT_SUCCESS) {
return git__rethrow(error, "Failed to read existing config file %s", cfg->file_path);
}
@@ -1011,8 +1014,15 @@ static int config_write(diskfile_backend *cfg, cvar_t *var)
break;
}
- /* Then replace the variable */
- error = git_filebuf_printf(&file, "\t%s = %s\n", var->name, var->value);
+ /*
+ * Then replace the variable. If the value is NULL, it
+ * means we want to delete it, so pretend everything went
+ * fine
+ */
+ if (var->value == NULL)
+ error = GIT_SUCCESS;
+ else
+ error = git_filebuf_printf(&file, "\t%s = %s\n", var->name, var->value);
if (error < GIT_SUCCESS) {
git__rethrow(error, "Failed to overwrite the variable");
break;
@@ -1068,7 +1078,7 @@ static int config_write(diskfile_backend *cfg, cvar_t *var)
else
error = git_filebuf_commit(&file);
- gitfo_free_buf(&cfg->reader.buffer);
+ git_futils_freebuffer(&cfg->reader.buffer);
return error;
}
diff --git a/src/errors.c b/src/errors.c
index 7da02b4f7..e9022c3d1 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -108,6 +108,13 @@ int git__throw(int error, const char *msg, ...)
const char *git_lasterror(void)
{
+ if (!g_last_error[0])
+ return NULL;
+
return g_last_error;
}
+void git_clearerror(void)
+{
+ g_last_error[0] = '\0';
+}
diff --git a/src/filebuf.c b/src/filebuf.c
index ca13e6181..acfdcd141 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -32,39 +32,39 @@ static const size_t WRITE_BUFFER_SIZE = (4096 * 2);
static int lock_file(git_filebuf *file, int flags)
{
- if (gitfo_exists(file->path_lock) == 0) {
+ if (git_futils_exists(file->path_lock) == 0) {
if (flags & GIT_FILEBUF_FORCE)
- gitfo_unlink(file->path_lock);
+ p_unlink(file->path_lock);
else
return git__throw(GIT_EOSERR, "Failed to lock file");
}
/* create path to the file buffer is required */
if (flags & GIT_FILEBUF_FORCE) {
- file->fd = gitfo_creat_locked_force(file->path_lock, 0644);
+ file->fd = git_futils_creat_locked_withpath(file->path_lock, 0644);
} else {
- file->fd = gitfo_creat_locked(file->path_lock, 0644);
+ file->fd = git_futils_creat_locked(file->path_lock, 0644);
}
if (file->fd < 0)
return git__throw(GIT_EOSERR, "Failed to create lock");
- if ((flags & GIT_FILEBUF_APPEND) && gitfo_exists(file->path_original) == 0) {
+ if ((flags & GIT_FILEBUF_APPEND) && git_futils_exists(file->path_original) == 0) {
git_file source;
char buffer[2048];
size_t read_bytes;
- source = gitfo_open(file->path_original, O_RDONLY);
+ source = p_open(file->path_original, O_RDONLY);
if (source < 0)
return git__throw(GIT_EOSERR, "Failed to lock file. Could not open %s", file->path_original);
- while ((read_bytes = gitfo_read(source, buffer, 2048)) > 0) {
- gitfo_write(file->fd, buffer, read_bytes);
+ while ((read_bytes = p_read(source, buffer, 2048)) > 0) {
+ p_write(file->fd, buffer, read_bytes);
if (file->digest)
git_hash_update(file->digest, buffer, read_bytes);
}
- gitfo_close(source);
+ p_close(source);
}
return GIT_SUCCESS;
@@ -73,10 +73,10 @@ static int lock_file(git_filebuf *file, int flags)
void git_filebuf_cleanup(git_filebuf *file)
{
if (file->fd >= 0)
- gitfo_close(file->fd);
+ p_close(file->fd);
- if (file->fd >= 0 && file->path_lock && gitfo_exists(file->path_lock) == GIT_SUCCESS)
- gitfo_unlink(file->path_lock);
+ if (file->fd >= 0 && file->path_lock && git_futils_exists(file->path_lock) == GIT_SUCCESS)
+ p_unlink(file->path_lock);
if (file->digest)
git_hash_free_ctx(file->digest);
@@ -102,7 +102,7 @@ static int write_normal(git_filebuf *file, const void *source, size_t len)
int result = 0;
if (len > 0) {
- result = gitfo_write(file->fd, (void *)source, len);
+ result = p_write(file->fd, (void *)source, len);
if (file->digest)
git_hash_update(file->digest, source, len);
}
@@ -130,7 +130,7 @@ static int write_deflate(git_filebuf *file, const void *source, size_t len)
have = file->buf_size - zs->avail_out;
- if (gitfo_write(file->fd, file->z_buf, have) < GIT_SUCCESS)
+ if (p_write(file->fd, file->z_buf, have) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to write to file");
} while (zs->avail_out == 0);
@@ -200,7 +200,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
char tmp_path[GIT_PATH_MAX];
/* Open the file as temporary for locking */
- file->fd = gitfo_mktemp(tmp_path, path);
+ file->fd = git_futils_mktmp(tmp_path, path);
if (file->fd < 0) {
error = GIT_EOSERR;
goto cleanup;
@@ -283,10 +283,10 @@ int git_filebuf_commit(git_filebuf *file)
if ((error = flush_buffer(file)) < GIT_SUCCESS)
goto cleanup;
- gitfo_close(file->fd);
+ p_close(file->fd);
file->fd = -1;
- error = gitfo_mv(file->path_lock, file->path_original);
+ error = git_futils_mv_atomic(file->path_lock, file->path_original);
cleanup:
git_filebuf_cleanup(file);
@@ -331,6 +331,7 @@ int git_filebuf_write(git_filebuf *file, const void *buff, size_t len)
error = file->write(file, buf, len);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to write to buffer");
+ return GIT_SUCCESS;
}
}
}
diff --git a/src/fileops.c b/src/fileops.c
index 2a5eb74ad..52aeb41a3 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -2,22 +2,45 @@
#include "fileops.h"
#include <ctype.h>
-int gitfo_mkdir_2file(const char *file_path)
+int git_futils_mv_atomic(const char *from, const char *to)
+{
+#ifdef GIT_WIN32
+ /*
+ * Win32 POSIX compilance my ass. If the destination
+ * file exists, the `rename` call fails. This is as
+ * close as it gets with the Win32 API.
+ */
+ return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
+#else
+ /* Don't even try this on Win32 */
+ if (!link(from, to)) {
+ p_unlink(from);
+ return GIT_SUCCESS;
+ }
+
+ if (!rename(from, to))
+ return GIT_SUCCESS;
+
+ return GIT_ERROR;
+#endif
+}
+
+int git_futils_mkpath2file(const char *file_path)
{
const int mode = 0755; /* or 0777 ? */
int error = GIT_SUCCESS;
char target_folder_path[GIT_PATH_MAX];
- error = git__dirname_r(target_folder_path, sizeof(target_folder_path), file_path);
+ error = git_path_dirname_r(target_folder_path, sizeof(target_folder_path), file_path);
if (error < GIT_SUCCESS)
return git__throw(GIT_EINVALIDPATH, "Failed to recursively build `%s` tree structure. Unable to parse parent folder name", file_path);
/* Does the containing folder exist? */
- if (gitfo_isdir(target_folder_path)) {
- git__joinpath(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */
+ if (git_futils_isdir(target_folder_path)) {
+ git_path_join(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */
/* Let's create the tree structure */
- error = gitfo_mkdir_recurs(target_folder_path, mode);
+ error = git_futils_mkdir_r(target_folder_path, mode);
if (error < GIT_SUCCESS)
return error; /* The callee already takes care of setting the correct error message. */
}
@@ -25,7 +48,7 @@ int gitfo_mkdir_2file(const char *file_path)
return GIT_SUCCESS;
}
-int gitfo_mktemp(char *path_out, const char *filename)
+int git_futils_mktmp(char *path_out, const char *filename)
{
int fd;
@@ -38,7 +61,7 @@ int gitfo_mktemp(char *path_out, const char *filename)
if (_mktemp_s(path_out, GIT_PATH_MAX) != 0)
return git__throw(GIT_EOSERR, "Failed to make temporary file %s", path_out);
- fd = gitfo_creat(path_out, 0744);
+ fd = p_creat(path_out, 0744);
#else
fd = mkstemp(path_out);
#endif
@@ -46,142 +69,79 @@ int gitfo_mktemp(char *path_out, const char *filename)
return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to create temporary file %s", path_out);
}
-int gitfo_open(const char *path, int flags)
-{
- int fd = open(path, flags | O_BINARY);
- return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to open %s", path);
-}
-
-int gitfo_creat(const char *path, int mode)
-{
- int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
- return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to create file. Could not open %s", path);
-}
-
-int gitfo_creat_force(const char *path, int mode)
+int git_futils_creat_withpath(const char *path, int mode)
{
- if (gitfo_mkdir_2file(path) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(path) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to create file %s", path);
- return gitfo_creat(path, mode);
+ return p_creat(path, mode);
}
-int gitfo_creat_locked(const char *path, int mode)
+int git_futils_creat_locked(const char *path, int mode)
{
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_EXCL, mode);
return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to create locked file. Could not open %s", path);
}
-int gitfo_creat_locked_force(const char *path, int mode)
+int git_futils_creat_locked_withpath(const char *path, int mode)
{
- if (gitfo_mkdir_2file(path) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(path) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to create locked file %s", path);
- return gitfo_creat_locked(path, mode);
+ return git_futils_creat_locked(path, mode);
}
-int gitfo_read(git_file fd, void *buf, size_t cnt)
+int git_futils_isdir(const char *path)
{
- char *b = buf;
- while (cnt) {
- ssize_t r = read(fd, b, cnt);
- if (r < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return git__throw(GIT_EOSERR, "Failed to read from file");
- }
- if (!r)
- break;
- cnt -= r;
- b += r;
- }
- return (int)(b - (char *)buf);
-}
+#ifdef GIT_WIN32
+ DWORD attr = GetFileAttributes(path);
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ return GIT_ERROR;
-int gitfo_write(git_file fd, void *buf, size_t cnt)
-{
- char *b = buf;
- while (cnt) {
- ssize_t r = write(fd, b, cnt);
- if (r < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return git__throw(GIT_EOSERR, "Failed to write to file");
- }
- if (!r) {
- errno = EPIPE;
- return git__throw(GIT_EOSERR, "Failed to write to file");
- }
- cnt -= r;
- b += r;
- }
- return GIT_SUCCESS;
-}
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) ? GIT_SUCCESS : GIT_ERROR;
-int gitfo_isdir(const char *path)
-{
+#else
struct stat st;
- int len, stat_error;
-
- if (!path)
- return git__throw(GIT_ENOTFOUND, "No path given to gitfo_isdir");
-
- len = strlen(path);
-
- /* win32: stat path for folders cannot end in a slash */
- if (path[len - 1] == '/') {
- char *path_fixed = NULL;
- path_fixed = git__strdup(path);
- path_fixed[len - 1] = 0;
- stat_error = gitfo_stat(path_fixed, &st);
- free(path_fixed);
- } else {
- stat_error = gitfo_stat(path, &st);
- }
-
- if (stat_error < GIT_SUCCESS)
- return git__throw(GIT_ENOTFOUND, "%s does not exist", path);
-
- if (!S_ISDIR(st.st_mode))
- return git__throw(GIT_ENOTFOUND, "%s is not a directory", path);
+ if (p_stat(path, &st) < GIT_SUCCESS)
+ return GIT_ERROR;
- return GIT_SUCCESS;
+ return S_ISDIR(st.st_mode) ? GIT_SUCCESS : GIT_ERROR;
+#endif
}
-int gitfo_isfile(const char *path)
+int git_futils_isfile(const char *path)
{
struct stat st;
int stat_error;
- if (!path)
- return git__throw(GIT_ENOTFOUND, "No path given to gitfo_isfile");
-
- stat_error = gitfo_stat(path, &st);
+ assert(path);
+ stat_error = p_stat(path, &st);
if (stat_error < GIT_SUCCESS)
- return git__throw(GIT_ENOTFOUND, "%s does not exist", path);
+ return -1;
if (!S_ISREG(st.st_mode))
- return git__throw(GIT_ENOTFOUND, "%s is not a file", path);
+ return -1;
- return GIT_SUCCESS;
+ return 0;
}
-int gitfo_exists(const char *path)
+int git_futils_exists(const char *path)
{
assert(path);
return access(path, F_OK);
}
-git_off_t gitfo_size(git_file fd)
+git_off_t git_futils_filesize(git_file fd)
{
struct stat sb;
- if (gitfo_fstat(fd, &sb))
- return git__throw(GIT_EOSERR, "Failed to get size of file. File missing or corrupted");
+ if (p_fstat(fd, &sb))
+ return GIT_ERROR;
+
return sb.st_size;
}
-int gitfo_read_file(gitfo_buf *obj, const char *path)
+int git_futils_readbuffer(git_fbuffer *obj, const char *path)
{
git_file fd;
size_t len;
@@ -190,28 +150,28 @@ int gitfo_read_file(gitfo_buf *obj, const char *path)
assert(obj && path && *path);
- if ((fd = gitfo_open(path, O_RDONLY)) < 0)
+ if ((fd = p_open(path, O_RDONLY)) < 0)
return git__throw(GIT_ERROR, "Failed to open %s for reading", path);
- if (((size = gitfo_size(fd)) < 0) || !git__is_sizet(size+1)) {
- gitfo_close(fd);
+ if (((size = git_futils_filesize(fd)) < 0) || !git__is_sizet(size+1)) {
+ p_close(fd);
return git__throw(GIT_ERROR, "Failed to read file `%s`. An error occured while calculating its size", path);
}
len = (size_t) size;
if ((buff = git__malloc(len + 1)) == NULL) {
- gitfo_close(fd);
+ p_close(fd);
return GIT_ENOMEM;
}
- if (gitfo_read(fd, buff, len) < 0) {
- gitfo_close(fd);
+ if (p_read(fd, buff, len) < 0) {
+ p_close(fd);
free(buff);
return git__throw(GIT_ERROR, "Failed to read file `%s`", path);
}
buff[len] = '\0';
- gitfo_close(fd);
+ p_close(fd);
obj->data = buff;
obj->len = len;
@@ -219,64 +179,33 @@ int gitfo_read_file(gitfo_buf *obj, const char *path)
return GIT_SUCCESS;
}
-void gitfo_free_buf(gitfo_buf *obj)
+void git_futils_freebuffer(git_fbuffer *obj)
{
assert(obj);
free(obj->data);
obj->data = NULL;
}
-int gitfo_mv(const char *from, const char *to)
-{
- int error;
-
-#ifdef GIT_WIN32
- /*
- * Win32 POSIX compilance my ass. If the destination
- * file exists, the `rename` call fails. This is as
- * close as it gets with the Win32 API.
- */
- error = MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
-#else
- /* Don't even try this on Win32 */
- if (!link(from, to)) {
- gitfo_unlink(from);
- return GIT_SUCCESS;
- }
- if (!rename(from, to))
- return GIT_SUCCESS;
-
- error = GIT_EOSERR;
-#endif
-
- if (error < GIT_SUCCESS)
- return git__throw(error, "Failed to move file from `%s` to `%s`", from, to);
-
- return GIT_SUCCESS;
-}
-
-int gitfo_mv_force(const char *from, const char *to)
+int git_futils_mv_withpath(const char *from, const char *to)
{
- if (gitfo_mkdir_2file(to) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(to) < GIT_SUCCESS)
return GIT_EOSERR; /* The callee already takes care of setting the correct error message. */
- return gitfo_mv(from, to); /* The callee already takes care of setting the correct error message. */
+ return git_futils_mv_atomic(from, to); /* The callee already takes care of setting the correct error message. */
}
-int gitfo_map_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
+int git_futils_mmap_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
{
- if (git__mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin) < GIT_SUCCESS)
- return GIT_EOSERR;
- return GIT_SUCCESS;
+ return p_mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin);
}
-void gitfo_free_map(git_map *out)
+void git_futils_mmap_free(git_map *out)
{
- git__munmap(out);
+ p_munmap(out);
}
-int gitfo_dirent(
+int git_futils_direach(
char *path,
size_t path_sz,
int (*fn)(void *, char *),
@@ -332,42 +261,7 @@ int gitfo_dirent(
return GIT_SUCCESS;
}
-#if GIT_PLATFORM_PATH_SEP == '/'
-void gitfo_posixify_path(char *GIT_UNUSED(path))
-{
- /* nothing to do*/
-}
-#else
-void gitfo_posixify_path(char *path)
-{
- while (*path) {
- if (*path == GIT_PLATFORM_PATH_SEP)
- *path = '/';
-
- path++;
- }
-}
-#endif
-
-int gitfo_retrieve_path_root_offset(const char *path)
-{
- int offset = 0;
-
-#ifdef GIT_WIN32
-
- /* Does the root of the path look like a windows drive ? */
- if (isalpha(path[0]) && (path[1] == ':'))
- offset += 2;
-
-#endif
-
- if (*(path + offset) == '/')
- return offset;
-
- return -1; /* Not a real error. Rather a signal than the path is not rooted */
-}
-
-int gitfo_mkdir_recurs(const char *path, int mode)
+int git_futils_mkdir_r(const char *path, int mode)
{
int error, root_path_offset;
char *pp, *sp;
@@ -379,14 +273,14 @@ int gitfo_mkdir_recurs(const char *path, int mode)
error = GIT_SUCCESS;
pp = path_copy;
- root_path_offset = gitfo_retrieve_path_root_offset(pp);
+ root_path_offset = git_path_root(pp);
if (root_path_offset > 0)
pp += root_path_offset; /* On Windows, will skip the drive name (eg. C: or D:) */
while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != NULL) {
- if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) {
+ if (sp != pp && git_futils_isdir(path_copy) < GIT_SUCCESS) {
*sp = 0;
- error = gitfo_mkdir(path_copy, mode);
+ error = p_mkdir(path_copy, mode);
/* Do not choke while trying to recreate an existing directory */
if (errno == EEXIST)
@@ -399,7 +293,7 @@ int gitfo_mkdir_recurs(const char *path, int mode)
}
if (*pp != '\0' && error == GIT_SUCCESS) {
- error = gitfo_mkdir(path, mode);
+ error = p_mkdir(path, mode);
if (errno == EEXIST)
error = GIT_SUCCESS;
}
@@ -412,155 +306,7 @@ int gitfo_mkdir_recurs(const char *path, int mode)
return GIT_SUCCESS;
}
-static int retrieve_previous_path_component_start(const char *path)
-{
- int offset, len, root_offset, start = 0;
-
- root_offset = gitfo_retrieve_path_root_offset(path);
- if (root_offset > -1)
- start += root_offset;
-
- len = strlen(path);
- offset = len - 1;
-
- /* Skip leading slash */
- if (path[start] == '/')
- start++;
-
- /* Skip trailing slash */
- if (path[offset] == '/')
- offset--;
-
- if (offset < root_offset)
- return git__throw(GIT_ERROR, "Failed to retrieve path component. Wrong offset");
-
- while (offset > start && path[offset-1] != '/') {
- offset--;
- }
-
- return offset;
-}
-
-int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, const char *base_path)
-{
- int len = 0, segment_len, only_dots, root_path_offset, error = GIT_SUCCESS;
- char *current;
- const char *buffer_out_start, *buffer_end;
-
- current = (char *)path;
- buffer_end = path + strlen(path);
- buffer_out_start = buffer_out;
-
- root_path_offset = gitfo_retrieve_path_root_offset(path);
- if (root_path_offset < 0) {
- if (base_path == NULL) {
- error = gitfo_getcwd(buffer_out, size);
- if (error < GIT_SUCCESS)
- return error; /* The callee already takes care of setting the correct error message. */
- } else {
- if (size < (strlen(base_path) + 1) * sizeof(char))
- return git__throw(GIT_EOVERFLOW, "Failed to prettify dir path: the base path is too long for the buffer.");
-
- strcpy(buffer_out, base_path);
- gitfo_posixify_path(buffer_out);
- git__joinpath(buffer_out, buffer_out, "");
- }
-
- len = strlen(buffer_out);
- buffer_out += len;
- }
-
- while (current < buffer_end) {
- /* Prevent multiple slashes from being added to the output */
- if (*current == '/' && len > 0 && buffer_out_start[len - 1] == '/') {
- current++;
- continue;
- }
-
- only_dots = 1;
- segment_len = 0;
-
- /* Copy path segment to the output */
- while (current < buffer_end && *current != '/')
- {
- only_dots &= (*current == '.');
- *buffer_out++ = *current++;
- segment_len++;
- len++;
- }
-
- /* Skip current directory */
- if (only_dots && segment_len == 1)
- {
- current++;
- buffer_out -= segment_len;
- len -= segment_len;
- continue;
- }
-
- /* Handle the double-dot upward directory navigation */
- if (only_dots && segment_len == 2)
- {
- current++;
- buffer_out -= segment_len;
-
- *buffer_out ='\0';
- len = retrieve_previous_path_component_start(buffer_out_start);
-
- /* Are we escaping out of the root dir? */
- if (len < 0)
- return git__throw(GIT_EINVALIDPATH, "Failed to normalize path `%s`. The path escapes out of the root directory", path);
-
- buffer_out = (char *)buffer_out_start + len;
- continue;
- }
-
- /* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */
- if (only_dots && segment_len > 0)
- return git__throw(GIT_EINVALIDPATH, "Failed to normalize path `%s`. The path contains a segment with three `.` or more", path);
-
- *buffer_out++ = '/';
- len++;
- }
-
- *buffer_out = '\0';
-
- return GIT_SUCCESS;
-}
-
-int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path, const char *base_path)
-{
- int error, path_len, i, root_offset;
- const char* pattern = "/..";
-
- path_len = strlen(path);
-
- /* Let's make sure the filename isn't empty nor a dot */
- if (path_len == 0 || (path_len == 1 && *path == '.'))
- return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path is either empty or equals `.`", path);
-
- /* Let's make sure the filename doesn't end with "/", "/." or "/.." */
- for (i = 1; path_len > i && i < 4; i++) {
- if (!strncmp(path + path_len - i, pattern, i))
- return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path);
- }
-
- error = gitfo_prettify_dir_path(buffer_out, size, path, base_path);
- if (error < GIT_SUCCESS)
- return error; /* The callee already takes care of setting the correct error message. */
-
- path_len = strlen(buffer_out);
- root_offset = gitfo_retrieve_path_root_offset(buffer_out) + 1;
- if (path_len == root_offset)
- return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path);
-
- /* Remove the trailing slash */
- buffer_out[path_len - 1] = '\0';
-
- return GIT_SUCCESS;
-}
-
-int gitfo_cmp_path(const char *name1, int len1, int isdir1,
+int git_futils_cmp_path(const char *name1, int len1, int isdir1,
const char *name2, int len2, int isdir2)
{
int len = len1 < len2 ? len1 : len2;
@@ -578,173 +324,3 @@ int gitfo_cmp_path(const char *name1, int len1, int isdir1,
return 0;
}
-int gitfo_getcwd(char *buffer_out, size_t size)
-{
- char *cwd_buffer;
-
- assert(buffer_out && size > 0);
-
-#ifdef GIT_WIN32
- cwd_buffer = _getcwd(buffer_out, size);
-#else
- cwd_buffer = getcwd(buffer_out, size);
-#endif
-
- if (cwd_buffer == NULL)
- return git__throw(GIT_EOSERR, "Failed to retrieve current working directory");
-
- gitfo_posixify_path(buffer_out);
-
- git__joinpath(buffer_out, buffer_out, ""); //Ensure the path ends with a trailing slash
-
- return GIT_SUCCESS;
-}
-
-#ifdef GIT_WIN32
-GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
-{
- long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
- winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
- winTime /= 10000000; /* Nano to seconds resolution */
- return (time_t)winTime;
-}
-
-static int do_lstat(const char *file_name, struct stat *buf)
-{
- WIN32_FILE_ATTRIBUTE_DATA fdata;
-
- if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
- int fMode = S_IREAD;
-
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- fMode |= S_IFDIR;
- else
- fMode |= S_IFREG;
-
- if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
- fMode |= S_IWRITE;
-
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- fMode |= S_IFLNK;
-
- buf->st_ino = 0;
- buf->st_gid = 0;
- buf->st_uid = 0;
- buf->st_nlink = 1;
- buf->st_mode = (mode_t)fMode;
- buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
- buf->st_dev = buf->st_rdev = (_getdrive() - 1);
- buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
- buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
- buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
- return GIT_SUCCESS;
- }
-
- switch (GetLastError()) {
- case ERROR_ACCESS_DENIED:
- case ERROR_SHARING_VIOLATION:
- case ERROR_LOCK_VIOLATION:
- case ERROR_SHARING_BUFFER_EXCEEDED:
- return GIT_EOSERR;
-
- case ERROR_BUFFER_OVERFLOW:
- case ERROR_NOT_ENOUGH_MEMORY:
- return GIT_ENOMEM;
-
- default:
- return GIT_EINVALIDPATH;
- }
-}
-
-int gitfo_lstat__w32(const char *file_name, struct stat *buf)
-{
- int namelen, error;
- char alt_name[GIT_PATH_MAX];
-
- if ((error = do_lstat(file_name, buf)) == GIT_SUCCESS)
- return GIT_SUCCESS;
-
- /* if file_name ended in a '/', Windows returned ENOENT;
- * try again without trailing slashes
- */
- if (error != GIT_EINVALIDPATH)
- return git__throw(GIT_EOSERR, "Failed to lstat file");
-
- namelen = strlen(file_name);
- if (namelen && file_name[namelen-1] != '/')
- return git__throw(GIT_EOSERR, "Failed to lstat file");
-
- while (namelen && file_name[namelen-1] == '/')
- --namelen;
-
- if (!namelen || namelen >= GIT_PATH_MAX)
- return git__throw(GIT_ENOMEM, "Failed to lstat file");
-
- memcpy(alt_name, file_name, namelen);
- alt_name[namelen] = 0;
- return do_lstat(alt_name, buf);
-}
-
-int gitfo_readlink__w32(const char *link, char *target, size_t target_len)
-{
- typedef DWORD (WINAPI *fpath_func)(HANDLE, LPTSTR, DWORD, DWORD);
- static fpath_func pGetFinalPath = NULL;
- HANDLE hFile;
- DWORD dwRet;
-
- /*
- * Try to load the pointer to pGetFinalPath dynamically, because
- * it is not available in platforms older than Vista
- */
- if (pGetFinalPath == NULL) {
- HINSTANCE library = LoadLibrary("kernel32");
-
- if (library != NULL)
- pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleA");
-
- if (pGetFinalPath == NULL)
- return git__throw(GIT_EOSERR,
- "'GetFinalPathNameByHandleA' is not available in this platform");
- }
-
- hFile = CreateFile(link, // file to open
- GENERIC_READ, // open for reading
- FILE_SHARE_READ, // share for reading
- NULL, // default security
- OPEN_EXISTING, // existing file only
- FILE_FLAG_BACKUP_SEMANTICS, // normal file
- NULL); // no attr. template
-
- if (hFile == INVALID_HANDLE_VALUE)
- return GIT_EOSERR;
-
- dwRet = pGetFinalPath(hFile, target, target_len, 0x0);
- if (dwRet >= target_len)
- return GIT_ENOMEM;
-
- CloseHandle(hFile);
-
- if (dwRet > 4) {
- /* Skip first 4 characters if they are "\\?\" */
- if (target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') {
- char tmp[GIT_PATH_MAX];
- unsigned int offset = 4;
- dwRet -= 4;
-
- /* \??\UNC\ */
- if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') {
- offset += 2;
- dwRet -= 2;
- target[offset] = '\\';
- }
-
- memcpy(tmp, target + offset, dwRet);
- memcpy(target, tmp, dwRet);
- }
- }
-
- target[dwRet] = '\0';
- return dwRet;
-}
-
-#endif
diff --git a/src/fileops.h b/src/fileops.h
index 953fc732f..4bfebe9d4 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -9,109 +9,98 @@
#include "common.h"
#include "map.h"
#include "dir.h"
-#include <fcntl.h>
-#include <time.h>
-
-#ifdef GIT_WIN32
-#define GIT_PLATFORM_PATH_SEP '\\'
-#else
-#define GIT_PLATFORM_PATH_SEP '/'
-#endif
-
-#define S_IFGITLINK 0160000
-#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
-
-#ifdef GIT_WIN32
-GIT_INLINE(int) link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
-{
- GIT_UNUSED_ARG(old)
- GIT_UNUSED_ARG(new)
- errno = ENOSYS;
- return -1;
-}
-
-GIT_INLINE(int) git__mkdir(const char *path, int GIT_UNUSED(mode))
-{
- GIT_UNUSED_ARG(mode)
- return mkdir(path);
-}
-
-extern int git__unlink(const char *path);
-extern int git__mkstemp(char *template);
-extern int git__fsync(int fd);
-
-# ifndef GIT__WIN32_NO_HIDE_FILEOPS
-# define unlink(p) git__unlink(p)
-# define mkstemp(t) git__mkstemp(t)
-# define mkdir(p,m) git__mkdir(p, m)
-# define fsync(fd) git__fsync(fd)
-# endif
-#endif /* GIT_WIN32 */
-
-
-#if !defined(O_BINARY)
-#define O_BINARY 0
-#endif
-
-#define GITFO_BUF_INIT {NULL, 0}
-
-typedef int git_file;
+#include "posix.h"
+#include "path.h"
+
+/**
+ * Filebuffer methods
+ *
+ * Read whole files into an in-memory buffer for processing
+ */
+#define GIT_FBUFFER_INIT {NULL, 0}
typedef struct { /* file io buffer */
void *data; /* data bytes */
size_t len; /* data length */
-} gitfo_buf;
-
-extern int gitfo_exists(const char *path);
-extern int gitfo_open(const char *path, int flags);
-extern int gitfo_creat(const char *path, int mode);
-extern int gitfo_creat_force(const char *path, int mode);
-extern int gitfo_creat_locked(const char *path, int mode);
-extern int gitfo_creat_locked_force(const char *path, int mode);
-extern int gitfo_mktemp(char *path_out, const char *filename);
-extern int gitfo_isdir(const char *path);
-extern int gitfo_isfile(const char *path);
-extern int gitfo_mkdir_recurs(const char *path, int mode);
-extern int gitfo_mkdir_2file(const char *path);
-#define gitfo_close(fd) close(fd)
-
-extern int gitfo_read(git_file fd, void *buf, size_t cnt);
-extern int gitfo_write(git_file fd, void *buf, size_t cnt);
-#define gitfo_lseek(f,n,w) lseek(f, n, w)
-extern git_off_t gitfo_size(git_file fd);
-
-extern int gitfo_read_file(gitfo_buf *obj, const char *path);
-extern void gitfo_free_buf(gitfo_buf *obj);
-
-/* Move (rename) a file; this operation is atomic */
-extern int gitfo_mv(const char *from, const char *to);
-
-/* Move a file (forced); this will create the destination
- * path if it doesn't exist */
-extern int gitfo_mv_force(const char *from, const char *to);
-
-#define gitfo_stat(p,b) stat(p, b)
-#define gitfo_fstat(f,b) fstat(f, b)
-
-#ifdef GIT_WIN32
-# define gitfo_lstat(p,b) gitfo_lstat__w32(p,b)
-# define gitfo_readlink(a, b, c) gitfo_readlink__w32(a, b, c)
-
- extern int gitfo_lstat__w32(const char *file_name, struct stat *buf);
- extern int gitfo_readlink__w32(const char *link, char *target, size_t target_len);
-#else
-# define gitfo_lstat(p,b) lstat(p,b)
-# define gitfo_readlink(a, b, c) readlink(a, b, c)
-#endif
-
-#define gitfo_unlink(p) unlink(p)
-#define gitfo_rmdir(p) rmdir(p)
-#define gitfo_chdir(p) chdir(p)
-#define gitfo_mkdir(p,m) mkdir(p, m)
-
-#define gitfo_mkstemp(t) mkstemp(t)
-#define gitfo_fsync(fd) fsync(fd)
-#define gitfo_chmod(p,m) chmod(p, m)
+} git_fbuffer;
+
+extern int git_futils_readbuffer(git_fbuffer *obj, const char *path);
+extern void git_futils_freebuffer(git_fbuffer *obj);
+
+/**
+ * File utils
+ *
+ * These are custom filesystem-related helper methods. They are
+ * rather high level, and wrap the underlying POSIX methods
+ *
+ * All these methods return GIT_SUCCESS on success,
+ * or an error code on failure and an error message is set.
+ */
+
+/**
+ * Check if a file exists and can be accessed.
+ */
+extern int git_futils_exists(const char *path);
+
+/**
+ * Create and open a file, while also
+ * creating all the folders in its path
+ */
+extern int git_futils_creat_withpath(const char *path, int mode);
+
+/**
+ * Create an open a process-locked file
+ */
+extern int git_futils_creat_locked(const char *path, int mode);
+
+/**
+ * Create an open a process-locked file, while
+ * also creating all the folders in its path
+ */
+extern int git_futils_creat_locked_withpath(const char *path, int mode);
+
+/**
+ * Check if the given path points to a directory
+ */
+extern int git_futils_isdir(const char *path);
+
+/**
+ * Check if the given path points to a regular file
+ */
+extern int git_futils_isfile(const char *path);
+
+/**
+ * Create a path recursively
+ */
+extern int git_futils_mkdir_r(const char *path, int mode);
+
+/**
+ * Create all the folders required to contain
+ * the full path of a file
+ */
+extern int git_futils_mkpath2file(const char *path);
+
+/**
+ * Create and open a temporary file with a `_git2_` suffix
+ */
+extern int git_futils_mktmp(char *path_out, const char *filename);
+
+/**
+ * Atomically rename a file on the filesystem
+ */
+extern int git_futils_mv_atomic(const char *from, const char *to);
+
+/**
+ * Move a file on the filesystem, create the
+ * destination path if it doesn't exist
+ */
+extern int git_futils_mv_withpath(const char *from, const char *to);
+
+
+/**
+ * Get the filesize in bytes of a file
+ */
+extern git_off_t git_futils_filesize(git_file fd);
/**
* Read-only map all or part of a file into memory.
@@ -128,7 +117,7 @@ extern int gitfo_mv_force(const char *from, const char *to);
* - GIT_SUCCESS on success;
* - GIT_EOSERR on an unspecified OS related error.
*/
-extern int gitfo_map_ro(
+extern int git_futils_mmap_ro(
git_map *out,
git_file fd,
git_off_t begin,
@@ -138,7 +127,7 @@ extern int gitfo_map_ro(
* Release the memory associated with a previous memory mapping.
* @param map the mapping description previously configured.
*/
-extern void gitfo_free_map(git_map *map);
+extern void git_futils_mmap_free(git_map *map);
/**
* Walk each directory entry, except '.' and '..', calling fn(state).
@@ -151,67 +140,13 @@ extern void gitfo_free_map(git_map *map);
* may modify the pathbuf, but only by appending new text.
* @param state to pass to fn as the first arg.
*/
-extern int gitfo_dirent(
+extern int git_futils_direach(
char *pathbuf,
size_t pathmax,
int (*fn)(void *, char *),
void *state);
-extern int gitfo_cmp_path(const char *name1, int len1, int isdir1,
+extern int git_futils_cmp_path(const char *name1, int len1, int isdir1,
const char *name2, int len2, int isdir2);
-extern int gitfo_getcwd(char *buffer_out, size_t size);
-
-/**
- * Clean up a provided absolute or relative directory path.
- *
- * This prettification relies on basic operations such as coalescing
- * multiple forward slashes into a single slash, removing '.' and
- * './' current directory segments, and removing parent directory
- * whenever '..' is encountered.
- *
- * If not empty, the returned path ends with a forward slash.
- *
- * For instance, this will turn "d1/s1///s2/..//../s3" into "d1/s3/".
- *
- * This only performs a string based analysis of the path.
- * No checks are done to make sure the path actually makes sense from
- * the file system perspective.
- *
- * @param buffer_out buffer to populate with the normalized path.
- * @param size buffer size.
- * @param path directory path to clean up.
- * @return
- * - GIT_SUCCESS on success;
- * - GIT_ERROR when the input path is invalid or escapes the current directory.
- */
-int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, const char *base_path);
-
-/**
- * Clean up a provided absolute or relative file path.
- *
- * This prettification relies on basic operations such as coalescing
- * multiple forward slashes into a single slash, removing '.' and
- * './' current directory segments, and removing parent directory
- * whenever '..' is encountered.
- *
- * For instance, this will turn "d1/s1///s2/..//../s3" into "d1/s3".
- *
- * This only performs a string based analysis of the path.
- * No checks are done to make sure the path actually makes sense from
- * the file system perspective.
- *
- * @param buffer_out buffer to populate with the normalized path.
- * @param size buffer size.
- * @param path file path to clean up.
- * @return
- * - GIT_SUCCESS on success;
- * - GIT_ERROR when the input path is invalid or escapes the current directory.
- */
-int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path, const char *base_path);
-
-void gitfo_posixify_path(char *path);
-
-int gitfo_retrieve_path_root_offset(const char *path);
-
#endif /* INCLUDE_fileops_h__ */
diff --git a/src/hash.c b/src/hash.c
index 775e4b4c1..b8b311bcb 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -28,10 +28,8 @@
#if defined(PPC_SHA1)
# include "ppc/sha1.h"
-#elif defined(OPENSSL_SHA1)
-# include <openssl/sha.h>
#else
-# include "block-sha1/sha1.h"
+# include "sha1.h"
#endif
struct git_hash_ctx {
diff --git a/src/hashtable.c b/src/hashtable.c
index b40737d67..86e5a113a 100644
--- a/src/hashtable.c
+++ b/src/hashtable.c
@@ -94,22 +94,22 @@ static void node_swap_with(git_hashtable_node *self, git_hashtable_node *other)
}
static int node_insert(git_hashtable *self, git_hashtable_node *new_node)
-{
+{
int iteration, hash_id;
- for (iteration = 0; iteration < MAX_LOOPS; iteration++) {
+ for (iteration = 0; iteration < MAX_LOOPS; iteration++) {
for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
git_hashtable_node *node;
node = node_with_hash(self, new_node->key, hash_id);
node_swap_with(new_node, node);
if(new_node->key == 0x0){
self->key_count++;
- return GIT_SUCCESS;
+ return GIT_SUCCESS;
}
}
}
- if (self->is_resizing)
+ if (self->is_resizing)
return git__throw(GIT_EBUSY, "Failed to insert node. Hashtable is currently resizing");
resize_to(self, self->size * 2);
@@ -130,7 +130,7 @@ static int insert_nodes(git_hashtable *self, git_hashtable_node *old_nodes, size
return GIT_SUCCESS;
}
-git_hashtable *git_hashtable_alloc(size_t min_size,
+git_hashtable *git_hashtable_alloc(size_t min_size,
git_hash_ptr hash,
git_hash_keyeq_ptr key_eq)
{
diff --git a/src/hashtable.h b/src/hashtable.h
index c3475b6ed..3a4e6a7e3 100644
--- a/src/hashtable.h
+++ b/src/hashtable.h
@@ -31,7 +31,7 @@ struct git_hashtable {
typedef struct git_hashtable_node git_hashtable_node;
typedef struct git_hashtable git_hashtable;
-git_hashtable *git_hashtable_alloc(size_t min_size,
+git_hashtable *git_hashtable_alloc(size_t min_size,
git_hash_ptr hash,
git_hash_keyeq_ptr key_eq);
void *git_hashtable_lookup(git_hashtable *h, const void *key);
diff --git a/src/index.c b/src/index.c
index 23fd52e09..06fa95c7b 100644
--- a/src/index.c
+++ b/src/index.c
@@ -170,7 +170,7 @@ static int index_initialize(git_index **index_out, git_repository *owner, const
git_vector_init(&index->entries, 32, index_cmp);
/* Check if index file is stored on disk already */
- if (gitfo_exists(index->index_file_path) == 0)
+ if (git_futils_exists(index->index_file_path) == 0)
index->on_disk = 1;
*index_out = index;
@@ -259,13 +259,13 @@ int git_index_read(git_index *index)
assert(index->index_file_path);
- if (!index->on_disk || gitfo_exists(index->index_file_path) < 0) {
+ if (!index->on_disk || git_futils_exists(index->index_file_path) < 0) {
git_index_clear(index);
index->on_disk = 0;
return GIT_SUCCESS;
}
- if (gitfo_stat(index->index_file_path, &indexst) < 0)
+ if (p_stat(index->index_file_path, &indexst) < 0)
return git__throw(GIT_EOSERR, "Failed to read index. %s does not exist or is corrupted", index->index_file_path);
if (!S_ISREG(indexst.st_mode))
@@ -273,9 +273,9 @@ int git_index_read(git_index *index)
if (indexst.st_mtime != index->last_modified) {
- gitfo_buf buffer;
+ git_fbuffer buffer;
- if ((error = gitfo_read_file(&buffer, index->index_file_path)) < GIT_SUCCESS)
+ if ((error = git_futils_readbuffer(&buffer, index->index_file_path)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to read index");
git_index_clear(index);
@@ -284,7 +284,7 @@ int git_index_read(git_index *index)
if (error == GIT_SUCCESS)
index->last_modified = indexst.st_mtime;
- gitfo_free_buf(&buffer);
+ git_futils_freebuffer(&buffer);
}
if (error < GIT_SUCCESS)
@@ -311,7 +311,7 @@ int git_index_write(git_index *index)
if ((error = git_filebuf_commit(&file)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write index");
- if (gitfo_stat(index->index_file_path, &indexst) == 0) {
+ if (p_stat(index->index_file_path, &indexst) == 0) {
index->last_modified = indexst.st_mtime;
index->on_disk = 1;
}
@@ -409,9 +409,9 @@ static int index_init_entry(git_index_entry *entry, git_index *index, const char
if (index->repository == NULL)
return git__throw(GIT_EBAREINDEX, "Failed to initialize entry. Repository is bare");
- git__joinpath(full_path, index->repository->path_workdir, rel_path);
+ git_path_join(full_path, index->repository->path_workdir, rel_path);
- if (gitfo_lstat(full_path, &st) < 0)
+ if (p_lstat(full_path, &st) < 0)
return git__throw(GIT_EOSERR, "Failed to initialize entry. '%s' cannot be opened", full_path);
if (stage < 0 || stage > 3)
@@ -549,7 +549,7 @@ static int read_tree_internal(git_index_tree **out,
if (count == -1) {
/* FIXME: return buffer_end or the end position for
* this single tree entry */
- *buffer_in = buffer_end;
+ *buffer_in = buffer_end;
*out = NULL;
free_tree(tree); /* Needs to be done manually */
return GIT_SUCCESS;
diff --git a/src/map.h b/src/map.h
index be569abc8..1dfbeeb4b 100644
--- a/src/map.h
+++ b/src/map.h
@@ -4,7 +4,7 @@
#include "common.h"
-/* git__mmap() prot values */
+/* p_mmap() prot values */
#define GIT_PROT_NONE 0x0
#define GIT_PROT_READ 0x1
#define GIT_PROT_WRITE 0x2
@@ -25,7 +25,7 @@ typedef struct { /* memory mapped buffer */
#endif
} git_map;
-extern int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset);
-extern int git__munmap(git_map *map);
+extern int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset);
+extern int p_munmap(git_map *map);
#endif /* INCLUDE_map_h__ */
diff --git a/src/odb.c b/src/odb.c
index 131093b83..b09931660 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -323,15 +323,15 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
char alternates_path[GIT_PATH_MAX];
char *buffer, *alternate;
- gitfo_buf alternates_buf = GITFO_BUF_INIT;
+ git_fbuffer alternates_buf = GIT_FBUFFER_INIT;
int error;
- git__joinpath(alternates_path, objects_dir, GIT_ALTERNATES_FILE);
+ git_path_join(alternates_path, objects_dir, GIT_ALTERNATES_FILE);
- if (gitfo_exists(alternates_path) < GIT_SUCCESS)
+ if (git_futils_exists(alternates_path) < GIT_SUCCESS)
return GIT_SUCCESS;
- if (gitfo_read_file(&alternates_buf, alternates_path) < GIT_SUCCESS)
+ if (git_futils_readbuffer(&alternates_buf, alternates_path) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to add backend. Can't read alternates");
buffer = (char *)alternates_buf.data;
@@ -346,7 +346,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
/* relative path: build based on the current `objects` folder */
if (*alternate == '.') {
- git__joinpath(full_path, objects_dir, alternate);
+ git_path_join(full_path, objects_dir, alternate);
alternate = full_path;
}
@@ -354,7 +354,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
break;
}
- gitfo_free_buf(&alternates_buf);
+ git_futils_freebuffer(&alternates_buf);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to load alternates");
return error;
@@ -620,7 +620,7 @@ int git_odb_open_wstream(git_odb_stream **stream, git_odb *db, size_t size, git_
return git__rethrow(error, "Failed to open write stream");
}
-int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oid)
+int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oid)
{
unsigned int i;
int error = GIT_ERROR;
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 510712bd8..2a2c464c7 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -97,7 +97,7 @@ static size_t object_file_name(char *name, size_t n, char *dir, const git_oid *i
}
-static size_t get_binary_object_header(obj_hdr *hdr, gitfo_buf *obj)
+static size_t get_binary_object_header(obj_hdr *hdr, git_fbuffer *obj)
{
unsigned char c;
unsigned char *data = obj->data;
@@ -199,7 +199,7 @@ static void set_stream_output(z_stream *s, void *out, size_t len)
}
-static int start_inflate(z_stream *s, gitfo_buf *obj, void *out, size_t len)
+static int start_inflate(z_stream *s, git_fbuffer *obj, void *out, size_t len)
{
int status;
@@ -309,7 +309,7 @@ static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
* of loose object data into packs. This format is no longer used, but
* we must still read it.
*/
-static int inflate_packlike_loose_disk_obj(git_rawobj *out, gitfo_buf *obj)
+static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_fbuffer *obj)
{
unsigned char *in, *buf;
obj_hdr hdr;
@@ -347,7 +347,7 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, gitfo_buf *obj)
return GIT_SUCCESS;
}
-static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
+static int inflate_disk_obj(git_rawobj *out, git_fbuffer *obj)
{
unsigned char head[64], *buf;
z_stream zs;
@@ -405,7 +405,7 @@ static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
static int read_loose(git_rawobj *out, const char *loc)
{
int error;
- gitfo_buf obj = GITFO_BUF_INIT;
+ git_fbuffer obj = GIT_FBUFFER_INIT;
assert(out && loc);
@@ -413,11 +413,11 @@ static int read_loose(git_rawobj *out, const char *loc)
out->len = 0;
out->type = GIT_OBJ_BAD;
- if (gitfo_read_file(&obj, loc) < 0)
+ if (git_futils_readbuffer(&obj, loc) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to read loose object. File not found");
error = inflate_disk_obj(out, &obj);
- gitfo_free_buf(&obj);
+ git_futils_freebuffer(&obj);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to read loose object");
}
@@ -434,7 +434,7 @@ static int read_header_loose(git_rawobj *out, const char *loc)
out->data = NULL;
- if ((fd = gitfo_open(loc, O_RDONLY)) < 0)
+ if ((fd = p_open(loc, O_RDONLY)) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to read loose object header. File not found");
init_stream(&zs, inflated_buffer, sizeof(inflated_buffer));
@@ -466,7 +466,7 @@ static int read_header_loose(git_rawobj *out, const char *loc)
cleanup:
finish_inflate(&zs);
- gitfo_close(fd);
+ p_close(fd);
if (error < GIT_SUCCESS)
return git__throw(error, "Failed to read loose object header. Header is corrupted");
@@ -477,7 +477,7 @@ cleanup:
static int locate_object(char *object_location, loose_backend *backend, const git_oid *oid)
{
object_file_name(object_location, GIT_PATH_MAX, backend->objects_dir, oid);
- return gitfo_exists(object_location);
+ return git_futils_exists(object_location);
}
/* Explore an entry of a directory and see if it matches a short oid */
@@ -490,7 +490,7 @@ int fn_locate_object_short_oid(void *state, char *pathbuf) {
return GIT_SUCCESS;
}
- if (!gitfo_exists(pathbuf) && gitfo_isdir(pathbuf)) {
+ if (!git_futils_exists(pathbuf) && git_futils_isdir(pathbuf)) {
/* We are already in the directory matching the 2 first hex characters,
* compare the first ncmp characters of the oids */
if (!memcmp(sstate->short_oid + 2,
@@ -534,14 +534,14 @@ static int locate_object_short_oid(char *object_location, git_oid *res_oid, loos
sprintf(object_location+dir_len, "%.2s/", state.short_oid);
/* Check that directory exists */
- if (gitfo_exists(object_location) || gitfo_isdir(object_location))
+ if (git_futils_exists(object_location) || git_futils_isdir(object_location))
return git__throw(GIT_ENOTFOUND, "Failed to locate object from short oid. Object not found");
state.dir_len = dir_len+3;
state.short_oid_len = len;
state.found = 0;
/* Explore directory to find a unique object matching short_oid */
- error = gitfo_dirent(object_location, GIT_PATH_MAX, fn_locate_object_short_oid, &state);
+ error = git_futils_direach(object_location, GIT_PATH_MAX, fn_locate_object_short_oid, &state);
if (error) {
return git__rethrow(error, "Failed to locate object from short oid");
}
@@ -684,7 +684,7 @@ int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
if (object_file_name(final_path, sizeof(final_path), backend->objects_dir, oid))
return GIT_ENOMEM;
- if ((error = gitfo_mkdir_2file(final_path)) < GIT_SUCCESS)
+ if ((error = git_futils_mkpath2file(final_path)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write loose backend");
stream->finished = 1;
@@ -749,7 +749,7 @@ int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend
stream->stream.free = &loose_backend__stream_free;
stream->stream.mode = GIT_STREAM_WRONLY;
- git__joinpath(tmp_path, backend->objects_dir, "tmp_object");
+ git_path_join(tmp_path, backend->objects_dir, "tmp_object");
error = git_filebuf_open(&stream->fbuf, tmp_path,
GIT_FILEBUF_HASH_CONTENTS |
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 2328f527c..59661a662 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -227,7 +227,7 @@ struct pack_backend {
-
+
/***********************************************************
*
* FORWARD DECLARATIONS
@@ -306,7 +306,7 @@ static off_t get_delta_base(struct pack_backend *backend,
static unsigned long packfile_unpack_header1(
size_t *sizep,
- git_otype *type,
+ git_otype *type,
const unsigned char *buf,
unsigned long len);
@@ -359,7 +359,7 @@ void pack_window_free_all(struct pack_backend *backend, struct pack_file *p)
backend->mapped -= w->window_map.len;
backend->open_windows--;
- gitfo_free_map(&w->window_map);
+ git_futils_mmap_free(&w->window_map);
p->windows = w->next;
free(w);
@@ -416,14 +416,14 @@ static int pack_window_close_lru(
if (lru_p) {
backend->mapped -= lru_w->window_map.len;
- gitfo_free_map(&lru_w->window_map);
+ git_futils_mmap_free(&lru_w->window_map);
if (lru_l)
lru_l->next = lru_w->next;
else {
lru_p->windows = lru_w->next;
if (!lru_p->windows && lru_p->pack_fd != keep_fd) {
- gitfo_close(lru_p->pack_fd);
+ p_close(lru_p->pack_fd);
lru_p->pack_fd = -1;
}
}
@@ -491,7 +491,7 @@ static unsigned char *pack_window_open(
while (backend->mapped_limit < backend->mapped &&
pack_window_close_lru(backend, p, p->pack_fd) == GIT_SUCCESS) {}
- if (gitfo_map_ro(&win->window_map, p->pack_fd,
+ if (git_futils_mmap_ro(&win->window_map, p->pack_fd,
win->offset, len) < GIT_SUCCESS)
return NULL;
@@ -539,7 +539,7 @@ static unsigned char *pack_window_open(
static void pack_index_free(struct pack_file *p)
{
if (p->index_map.data) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
p->index_map.data = NULL;
}
}
@@ -555,15 +555,15 @@ static int pack_index_check(const char *path, struct pack_file *p)
struct stat st;
/* TODO: properly open the file without access time */
- git_file fd = gitfo_open(path, O_RDONLY /*| O_NOATIME */);
+ git_file fd = p_open(path, O_RDONLY /*| O_NOATIME */);
int error;
if (fd < 0)
return git__throw(GIT_EOSERR, "Failed to check index. File missing or corrupted");
- if (gitfo_fstat(fd, &st) < GIT_SUCCESS) {
- gitfo_close(fd);
+ if (p_fstat(fd, &st) < GIT_SUCCESS) {
+ p_close(fd);
return git__throw(GIT_EOSERR, "Failed to check index. File appears to be corrupted");
}
@@ -573,12 +573,12 @@ static int pack_index_check(const char *path, struct pack_file *p)
idx_size = (size_t)st.st_size;
if (idx_size < 4 * 256 + 20 + 20) {
- gitfo_close(fd);
+ p_close(fd);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Object is corrupted");
}
- error = gitfo_map_ro(&p->index_map, fd, 0, idx_size);
- gitfo_close(fd);
+ error = git_futils_mmap_ro(&p->index_map, fd, 0, idx_size);
+ p_close(fd);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to check index");
@@ -589,7 +589,7 @@ static int pack_index_check(const char *path, struct pack_file *p)
version = ntohl(hdr->idx_version);
if (version < 2 || version > 2) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Unsupported index version");
}
@@ -605,7 +605,7 @@ static int pack_index_check(const char *path, struct pack_file *p)
for (i = 0; i < 256; i++) {
uint32_t n = ntohl(index[i]);
if (n < nr) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Index is non-monotonic");
}
nr = n;
@@ -620,7 +620,7 @@ static int pack_index_check(const char *path, struct pack_file *p)
* - 20-byte SHA1 file checksum
*/
if (idx_size != 4*256 + nr * 24 + 20 + 20) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Object is corrupted");
}
} else if (version == 2) {
@@ -644,14 +644,14 @@ static int pack_index_check(const char *path, struct pack_file *p)
max_size += (nr - 1)*8;
if (idx_size < min_size || idx_size > max_size) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Wrong index size");
}
/* Make sure that off_t is big enough to access the whole pack...
* Is this an issue in libgit2? It shouldn't. */
if (idx_size != min_size && (sizeof(off_t) <= 4)) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOSERR, "Failed to check index. off_t not big enough to access the whole pack");
}
}
@@ -738,7 +738,7 @@ static void packfile_free(struct pack_backend *backend, struct pack_file *p)
pack_window_free_all(backend, p);
if (p->pack_fd != -1)
- gitfo_close(p->pack_fd);
+ p_close(p->pack_fd);
pack_index_free(p);
@@ -757,8 +757,8 @@ static int packfile_open(struct pack_file *p)
return git__throw(GIT_ENOTFOUND, "Failed to open packfile. File not found");
/* TODO: open with noatime */
- p->pack_fd = gitfo_open(p->pack_name, O_RDONLY);
- if (p->pack_fd < 0 || gitfo_fstat(p->pack_fd, &st) < GIT_SUCCESS)
+ p->pack_fd = p_open(p->pack_name, O_RDONLY);
+ if (p->pack_fd < 0 || p_fstat(p->pack_fd, &st) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to open packfile. File appears to be corrupted");
/* If we created the struct before we had the pack we lack size. */
@@ -783,7 +783,7 @@ static int packfile_open(struct pack_file *p)
#endif
/* Verify we recognize this pack file format. */
- if (gitfo_read(p->pack_fd, &hdr, sizeof(hdr)) < GIT_SUCCESS)
+ if (p_read(p->pack_fd, &hdr, sizeof(hdr)) < GIT_SUCCESS)
goto cleanup;
if (hdr.hdr_signature != htonl(PACK_SIGNATURE))
@@ -796,10 +796,10 @@ static int packfile_open(struct pack_file *p)
if (p->num_objects != ntohl(hdr.hdr_entries))
goto cleanup;
- if (gitfo_lseek(p->pack_fd, p->pack_size - GIT_OID_RAWSZ, SEEK_SET) == -1)
+ if (p_lseek(p->pack_fd, p->pack_size - GIT_OID_RAWSZ, SEEK_SET) == -1)
goto cleanup;
- if (gitfo_read(p->pack_fd, sha1.id, GIT_OID_RAWSZ) < GIT_SUCCESS)
+ if (p_read(p->pack_fd, sha1.id, GIT_OID_RAWSZ) < GIT_SUCCESS)
goto cleanup;
idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
@@ -807,10 +807,10 @@ static int packfile_open(struct pack_file *p)
if (git_oid_cmp(&sha1, (git_oid *)idx_sha1) != 0)
goto cleanup;
- return GIT_SUCCESS;
+ return GIT_SUCCESS;
cleanup:
- gitfo_close(p->pack_fd);
+ p_close(p->pack_fd);
p->pack_fd = -1;
return git__throw(GIT_EPACKCORRUPTED, "Failed to packfile. Pack is corrupted");
}
@@ -838,11 +838,11 @@ static int packfile_check(struct pack_file **pack_out, const char *path)
memcpy(p->pack_name, path, path_len);
strcpy(p->pack_name + path_len, ".keep");
- if (gitfo_exists(p->pack_name) == GIT_SUCCESS)
+ if (git_futils_exists(p->pack_name) == GIT_SUCCESS)
p->pack_keep = 1;
strcpy(p->pack_name + path_len, ".pack");
- if (gitfo_stat(p->pack_name, &st) < GIT_SUCCESS || !S_ISREG(st.st_mode)) {
+ if (p_stat(p->pack_name, &st) < GIT_SUCCESS || !S_ISREG(st.st_mode)) {
free(p);
return git__throw(GIT_ENOTFOUND, "Failed to check packfile. File not found");
}
@@ -899,7 +899,7 @@ static int packfile_refresh_all(struct pack_backend *backend)
if (backend->pack_folder == NULL)
return GIT_SUCCESS;
- if (gitfo_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
+ if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
return git__throw(GIT_ENOTFOUND, "Failed to refresh packfiles. Backend not found");
if (st.st_mtime != backend->pack_folder_mtime) {
@@ -907,7 +907,7 @@ static int packfile_refresh_all(struct pack_backend *backend)
strcpy(path, backend->pack_folder);
/* reload all packs */
- error = gitfo_dirent(path, GIT_PATH_MAX, packfile_load__cb, (void *)backend);
+ error = git_futils_direach(path, GIT_PATH_MAX, packfile_load__cb, (void *)backend);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to refresh packfiles");
@@ -1068,7 +1068,7 @@ static int pack_entry_find1(
return git__rethrow(error, "Failed to find pack entry. Couldn't find offset");
/* we found a unique entry in the index;
- * make sure the packfile backing the index
+ * make sure the packfile backing the index
* still exists on disk */
if (p->pack_fd == -1 && packfile_open(p) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to find pack entry. Packfile doesn't exist on disk");
@@ -1177,7 +1177,7 @@ static int pack_entry_find_prefix(
static unsigned long packfile_unpack_header1(
size_t *sizep,
- git_otype *type,
+ git_otype *type,
const unsigned char *buf,
unsigned long len)
{
@@ -1385,7 +1385,7 @@ static int packfile_unpack(
size_t size = 0;
git_otype type;
- /*
+ /*
* TODO: optionally check the CRC on the packfile
*/
@@ -1549,8 +1549,8 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend->window_size = DEFAULT_WINDOW_SIZE;
backend->mapped_limit = DEFAULT_MAPPED_LIMIT;
- git__joinpath(path, objects_dir, "pack");
- if (gitfo_isdir(path) == GIT_SUCCESS) {
+ git_path_join(path, objects_dir, "pack");
+ if (git_futils_isdir(path) == GIT_SUCCESS) {
backend->pack_folder = git__strdup(path);
backend->pack_folder_mtime = 0;
diff --git a/src/oid.c b/src/oid.c
index 3e3237f9c..1f4a652c9 100644
--- a/src/oid.c
+++ b/src/oid.c
@@ -49,19 +49,37 @@ static signed char from_hex[] = {
};
static char to_hex[] = "0123456789abcdef";
-int git_oid_fromstr(git_oid *out, const char *str)
+int git_oid_fromstrn(git_oid *out, const char *str, size_t length)
{
size_t p;
- for (p = 0; p < sizeof(out->id); p++, str += 2) {
- int v = (from_hex[(unsigned char)str[0]] << 4)
- | from_hex[(unsigned char)str[1]];
+
+ if (length > GIT_OID_HEXSZ)
+ length = GIT_OID_HEXSZ;
+
+ if (length % 2)
+ length--;
+
+ for (p = 0; p < length; p += 2) {
+ int v = (from_hex[(unsigned char)str[p + 0]] << 4)
+ | from_hex[(unsigned char)str[p + 1]];
+
if (v < 0)
return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is not a valid sha1 hash");
- out->id[p] = (unsigned char)v;
+
+ out->id[p / 2] = (unsigned char)v;
}
+
+ for (; p < GIT_OID_HEXSZ; p += 2)
+ out->id[p / 2] = 0x0;
+
return GIT_SUCCESS;
}
+int git_oid_fromstr(git_oid *out, const char *str)
+{
+ return git_oid_fromstrn(out, str, GIT_OID_HEXSZ);
+}
+
GIT_INLINE(char) *fmt_one(char *str, unsigned int val)
{
*str++ = to_hex[val >> 4];
@@ -287,7 +305,7 @@ void git_oid_shorten_free(git_oid_shorten *os)
*
* - Each normal node points to 16 children (one for each possible
* character in the oid). This is *not* stored in an array of
- * pointers, because in a 64-bit arch this would be sucking
+ * pointers, because in a 64-bit arch this would be sucking
* 16*sizeof(void*) = 128 bytes of memory per node, which is fucking
* insane. What we do is store Node Indexes, and use these indexes
* to look up each node in the om->index array. These indexes are
diff --git a/src/path.c b/src/path.c
new file mode 100644
index 000000000..1f7a16679
--- /dev/null
+++ b/src/path.c
@@ -0,0 +1,254 @@
+#include "common.h"
+#include "path.h"
+#include "posix.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git_path_basename_r(char *buffer, size_t bufflen, const char *path)
+{
+ const char *endp, *startp;
+ int len, result;
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+ startp = ".";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Strip trailing slashes */
+ endp = path + strlen(path) - 1;
+ while (endp > path && *endp == '/')
+ endp--;
+
+ /* All slashes becomes "/" */
+ if (endp == path && *endp == '/') {
+ startp = "/";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Find the start of the base */
+ startp = endp;
+ while (startp > path && *(startp - 1) != '/')
+ startp--;
+
+ len = endp - startp +1;
+
+Exit:
+ result = len;
+ if (buffer == NULL) {
+ return result;
+ }
+ if (len > (int)bufflen-1) {
+ len = (int)bufflen-1;
+ result = GIT_ENOMEM;
+ }
+
+ if (len >= 0) {
+ memmove(buffer, startp, len);
+ buffer[len] = 0;
+ }
+ return result;
+}
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git_path_dirname_r(char *buffer, size_t bufflen, const char *path)
+{
+ const char *endp;
+ int result, len;
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+ path = ".";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Strip trailing slashes */
+ endp = path + strlen(path) - 1;
+ while (endp > path && *endp == '/')
+ endp--;
+
+ /* Find the start of the dir */
+ while (endp > path && *endp != '/')
+ endp--;
+
+ /* Either the dir is "/" or there are no slashes */
+ if (endp == path) {
+ path = (*endp == '/') ? "/" : ".";
+ len = 1;
+ goto Exit;
+ }
+
+ do {
+ endp--;
+ } while (endp > path && *endp == '/');
+
+ len = endp - path +1;
+
+Exit:
+ result = len;
+ if (len+1 > GIT_PATH_MAX) {
+ return GIT_ENOMEM;
+ }
+ if (buffer == NULL)
+ return result;
+
+ if (len > (int)bufflen-1) {
+ len = (int)bufflen-1;
+ result = GIT_ENOMEM;
+ }
+
+ if (len >= 0) {
+ memmove(buffer, path, len);
+ buffer[len] = 0;
+ }
+ return result;
+}
+
+
+char *git_path_dirname(const char *path)
+{
+ char *dname = NULL;
+ int len;
+
+ len = (path ? strlen(path) : 0) + 2;
+ dname = (char *)git__malloc(len);
+ if (dname == NULL)
+ return NULL;
+
+ if (git_path_dirname_r(dname, len, path) < GIT_SUCCESS) {
+ free(dname);
+ return NULL;
+ }
+
+ return dname;
+}
+
+char *git_path_basename(const char *path)
+{
+ char *bname = NULL;
+ int len;
+
+ len = (path ? strlen(path) : 0) + 2;
+ bname = (char *)git__malloc(len);
+ if (bname == NULL)
+ return NULL;
+
+ if (git_path_basename_r(bname, len, path) < GIT_SUCCESS) {
+ free(bname);
+ return NULL;
+ }
+
+ return bname;
+}
+
+
+const char *git_path_topdir(const char *path)
+{
+ size_t len;
+ int i;
+
+ assert(path);
+ len = strlen(path);
+
+ if (!len || path[len - 1] != '/')
+ return NULL;
+
+ for (i = len - 2; i >= 0; --i)
+ if (path[i] == '/')
+ break;
+
+ return &path[i + 1];
+}
+
+void git_path_join_n(char *buffer_out, int count, ...)
+{
+ va_list ap;
+ int i;
+ char *buffer_start = buffer_out;
+
+ va_start(ap, count);
+ for (i = 0; i < count; ++i) {
+ const char *path;
+ int len;
+
+ path = va_arg(ap, const char *);
+
+ assert((i == 0) || path != buffer_start);
+
+ if (i > 0 && *path == '/' && buffer_out > buffer_start && buffer_out[-1] == '/')
+ path++;
+
+ if (!*path)
+ continue;
+
+ len = strlen(path);
+ memmove(buffer_out, path, len);
+ buffer_out = buffer_out + len;
+
+ if (i < count - 1 && buffer_out[-1] != '/')
+ *buffer_out++ = '/';
+ }
+ va_end(ap);
+
+ *buffer_out = '\0';
+}
+
+int git_path_root(const char *path)
+{
+ int offset = 0;
+
+#ifdef GIT_WIN32
+ /* Does the root of the path look like a windows drive ? */
+ if (isalpha(path[0]) && (path[1] == ':'))
+ offset += 2;
+#endif
+
+ if (*(path + offset) == '/')
+ return offset;
+
+ return -1; /* Not a real error. Rather a signal than the path is not rooted */
+}
+
+int git_path_prettify(char *path_out, const char *path, const char *base)
+{
+ char *result;
+
+ if (base == NULL || git_path_root(path) >= 0) {
+ result = p_realpath(path, path_out);
+ } else {
+ char aux_path[GIT_PATH_MAX];
+ git_path_join(aux_path, base, path);
+ result = p_realpath(aux_path, path_out);
+ }
+
+ return result ? GIT_SUCCESS : GIT_EOSERR;
+}
+
+int git_path_prettify_dir(char *path_out, const char *path, const char *base)
+{
+ size_t end;
+
+ if (git_path_prettify(path_out, path, base) < GIT_SUCCESS)
+ return GIT_EOSERR;
+
+ end = strlen(path_out);
+
+ if (end && path_out[end - 1] != '/') {
+ path_out[end] = '/';
+ path_out[end + 1] = '\0';
+ }
+
+ return GIT_SUCCESS;
+}
diff --git a/src/path.h b/src/path.h
new file mode 100644
index 000000000..36e22a768
--- /dev/null
+++ b/src/path.h
@@ -0,0 +1,81 @@
+/*
+ * posix.h - Path management methods
+ */
+#ifndef INCLUDE_path_h__
+#define INCLUDE_path_h__
+
+#include "common.h"
+
+/*
+ * The dirname() function shall take a pointer to a character string
+ * that contains a pathname, and return a pointer to a string that is a
+ * pathname of the parent directory of that file. Trailing '/' characters
+ * in the path are not counted as part of the path.
+ *
+ * If path does not contain a '/', then dirname() shall return a pointer to
+ * the string ".". If path is a null pointer or points to an empty string,
+ * dirname() shall return a pointer to the string "." .
+ *
+ * The `git_path_dirname` implementation is thread safe. The returned
+ * string must be manually free'd.
+ *
+ * The `git_path_dirname_r` implementation expects a string allocated
+ * by the user with big enough size.
+ */
+extern char *git_path_dirname(const char *path);
+extern int git_path_dirname_r(char *buffer, size_t bufflen, const char *path);
+
+/*
+ * This function returns the basename of the file, which is the last
+ * part of its full name given by fname, with the drive letter and
+ * leading directories stripped off. For example, the basename of
+ * c:/foo/bar/file.ext is file.ext, and the basename of a:foo is foo.
+ *
+ * Trailing slashes and backslashes are significant: the basename of
+ * c:/foo/bar/ is an empty string after the rightmost slash.
+ *
+ * The `git_path_basename` implementation is thread safe. The returned
+ * string must be manually free'd.
+ *
+ * The `git_path_basename_r` implementation expects a string allocated
+ * by the user with big enough size.
+ */
+extern char *git_path_basename(const char *path);
+extern int git_path_basename_r(char *buffer, size_t bufflen, const char *path);
+
+extern const char *git_path_topdir(const char *path);
+
+/**
+ * Join two paths together. Takes care of properly fixing the
+ * middle slashes and everything
+ *
+ * The paths are joined together into buffer_out; this is expected
+ * to be an user allocated buffer of `GIT_PATH_MAX` size
+ */
+extern void git_path_join_n(char *buffer_out, int npath, ...);
+
+GIT_INLINE(void) git_path_join(char *buffer_out, const char *path_a, const char *path_b)
+{
+ git_path_join_n(buffer_out, 2, path_a, path_b);
+}
+
+int git_path_root(const char *path);
+
+int git_path_prettify(char *path_out, const char *path, const char *base);
+int git_path_prettify_dir(char *path_out, const char *path, const char *base);
+
+#ifdef GIT_WIN32
+GIT_INLINE(void) git_path_mkposix(char *path)
+{
+ while (*path) {
+ if (*path == '\\')
+ *path = '/';
+
+ path++;
+ }
+}
+#else
+# define git_path_mkposix(p) /* blank */
+#endif
+
+#endif
diff --git a/src/posix.c b/src/posix.c
new file mode 100644
index 000000000..9dbebbd57
--- /dev/null
+++ b/src/posix.c
@@ -0,0 +1,74 @@
+#include "common.h"
+#include "posix.h"
+#include "path.h"
+#include <stdio.h>
+#include <ctype.h>
+
+int p_open(const char *path, int flags)
+{
+ return open(path, flags | O_BINARY);
+}
+
+int p_creat(const char *path, int mode)
+{
+ return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
+}
+
+int p_read(git_file fd, void *buf, size_t cnt)
+{
+ char *b = buf;
+ while (cnt) {
+ ssize_t r = read(fd, b, cnt);
+ if (r < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return GIT_EOSERR;
+ }
+ if (!r)
+ break;
+ cnt -= r;
+ b += r;
+ }
+ return (int)(b - (char *)buf);
+}
+
+int p_write(git_file fd, void *buf, size_t cnt)
+{
+ char *b = buf;
+ while (cnt) {
+ ssize_t r = write(fd, b, cnt);
+ if (r < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return GIT_EOSERR;
+ }
+ if (!r) {
+ errno = EPIPE;
+ return GIT_EOSERR;
+ }
+ cnt -= r;
+ b += r;
+ }
+ return GIT_SUCCESS;
+}
+
+int p_getcwd(char *buffer_out, size_t size)
+{
+ char *cwd_buffer;
+
+ assert(buffer_out && size > 0);
+
+#ifdef GIT_WIN32
+ cwd_buffer = _getcwd(buffer_out, size);
+#else
+ cwd_buffer = getcwd(buffer_out, size);
+#endif
+
+ if (cwd_buffer == NULL)
+ return git__throw(GIT_EOSERR, "Failed to retrieve current working directory");
+
+ git_path_mkposix(buffer_out);
+
+ git_path_join(buffer_out, buffer_out, ""); //Ensure the path ends with a trailing slash
+ return GIT_SUCCESS;
+}
diff --git a/src/posix.h b/src/posix.h
new file mode 100644
index 000000000..eaa89383d
--- /dev/null
+++ b/src/posix.h
@@ -0,0 +1,54 @@
+/*
+ * posix.h - OS agnostic POSIX calls
+ */
+#ifndef INCLUDE_posix_h__
+#define INCLUDE_posix_h__
+
+#include "common.h"
+#include <fcntl.h>
+#include <time.h>
+
+#ifdef GIT_WIN32
+# include "win32/posix.h"
+#else
+# include "unix/posix.h"
+#endif
+
+#define S_IFGITLINK 0160000
+#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
+
+#if !defined(O_BINARY)
+#define O_BINARY 0
+#endif
+
+typedef int git_file;
+
+
+/**
+ * Standard POSIX Methods
+ *
+ * All the methods starting with the `p_` prefix are
+ * direct ports of the standard POSIX methods.
+ *
+ * Some of the methods are slightly wrapped to provide
+ * saner defaults. Some of these methods are emulated
+ * in Windows platforns.
+ *
+ * Use your manpages to check the docs on these.
+ * Straightforward
+ */
+extern int p_open(const char *path, int flags);
+extern int p_creat(const char *path, int mode);
+extern int p_read(git_file fd, void *buf, size_t cnt);
+extern int p_write(git_file fd, void *buf, size_t cnt);
+extern int p_getcwd(char *buffer_out, size_t size);
+
+#define p_lseek(f,n,w) lseek(f, n, w)
+#define p_stat(p,b) stat(p, b)
+#define p_fstat(f,b) fstat(f, b)
+#define p_chdir(p) chdir(p)
+#define p_rmdir(p) rmdir(p)
+#define p_chmod(p,m) chmod(p, m)
+#define p_close(fd) close(fd)
+
+#endif
diff --git a/src/pqueue.c b/src/pqueue.c
index 6307175e3..9883a35d8 100644
--- a/src/pqueue.c
+++ b/src/pqueue.c
@@ -11,7 +11,7 @@
* Copyright 2010 Volkan Yazıcı <volkan.yazici@gmail.com>
* Copyright 2006-2010 The Apache Software Foundation
*
- * This file is licensed under the Apache 2.0 license, which
+ * This file is licensed under the Apache 2.0 license, which
* supposedly makes it compatible with the GPLv2 that libgit2 uses.
*
* Check the Apache license at:
diff --git a/src/pqueue.h b/src/pqueue.h
index 7a1394803..ef8362c33 100644
--- a/src/pqueue.h
+++ b/src/pqueue.h
@@ -11,7 +11,7 @@
* Copyright 2010 Volkan Yazıcı <volkan.yazici@gmail.com>
* Copyright 2006-2010 The Apache Software Foundation
*
- * This file is licensed under the Apache 2.0 license, which
+ * This file is licensed under the Apache 2.0 license, which
* supposedly makes it compatible with the GPLv2 that libgit2 uses.
*
* Check the Apache license at:
diff --git a/src/refs.c b/src/refs.c
index ac13736eb..eea96adba 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -51,7 +51,7 @@ static uint32_t reftable_hash(const void *key, int hash_id)
static uint32_t hash_seeds[GIT_HASHTABLE_HASHES] = {
2147483647,
0x5d20bb23,
- 0x7daaab3c
+ 0x7daaab3c
};
return git__hash(key, strlen((const char *)key), hash_seeds[hash_id]);
@@ -59,11 +59,11 @@ static uint32_t reftable_hash(const void *key, int hash_id)
static void reference_free(git_reference *reference);
static int reference_create(git_reference **ref_out, git_repository *repo, const char *name, git_rtype type);
-static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *repo_path, const char *ref_name);
+static int reference_read(git_fbuffer *file_content, time_t *mtime, const char *repo_path, const char *ref_name);
/* loose refs */
-static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content);
-static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content);
+static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content);
+static int loose_parse_oid(git_reference *ref, git_fbuffer *file_content);
static int loose_lookup(git_reference **ref_out, git_repository *repo, const char *name, int skip_symbolic);
static int loose_write(git_reference *ref);
static int loose_update(git_reference *ref);
@@ -80,9 +80,6 @@ static int packed_sort(const void *a, const void *b);
static int packed_write(git_repository *repo);
/* internal helpers */
-static int reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target, int force);
-static int reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id, int force);
-static int reference_rename(git_reference *ref, const char *new_name, int force);
static int reference_available(git_repository *repo, const char *ref, const char *old_ref);
/* name normalization */
@@ -153,15 +150,15 @@ cleanup:
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference");
}
-static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *repo_path, const char *ref_name)
+static int reference_read(git_fbuffer *file_content, time_t *mtime, const char *repo_path, const char *ref_name)
{
struct stat st;
char path[GIT_PATH_MAX];
/* Determine the full path of the file */
- git__joinpath(path, repo_path, ref_name);
+ git_path_join(path, repo_path, ref_name);
- if (gitfo_stat(path, &st) < 0 || S_ISDIR(st.st_mode))
+ if (p_stat(path, &st) < 0 || S_ISDIR(st.st_mode))
return git__throw(GIT_ENOTFOUND,
"Cannot read reference file '%s'", ref_name);
@@ -169,7 +166,7 @@ static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *re
*mtime = st.st_mtime;
if (file_content)
- return gitfo_read_file(file_content, path);
+ return git_futils_readbuffer(file_content, path);
return GIT_SUCCESS;
}
@@ -184,7 +181,7 @@ static int loose_update(git_reference *ref)
{
int error;
time_t ref_time;
- gitfo_buf ref_file = GITFO_BUF_INIT;
+ git_fbuffer ref_file = GIT_FBUFFER_INIT;
if (ref->type & GIT_REF_PACKED)
return packed_load(ref->owner);
@@ -208,7 +205,7 @@ static int loose_update(git_reference *ref)
error = git__throw(GIT_EOBJCORRUPTED,
"Invalid reference type (%d) for loose reference", ref->type);
- gitfo_free_buf(&ref_file);
+ git_futils_freebuffer(&ref_file);
cleanup:
if (error != GIT_SUCCESS) {
@@ -219,7 +216,7 @@ cleanup:
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to update loose reference");
}
-static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
+static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content)
{
const unsigned int header_len = strlen(GIT_SYMREF);
const char *refname_start;
@@ -233,9 +230,9 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
return git__throw(GIT_EOBJCORRUPTED,
"Failed to parse loose reference. Object too short");
- /*
+ /*
* Assume we have already checked for the header
- * before calling this function
+ * before calling this function
*/
refname_start += header_len;
@@ -258,7 +255,7 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
return GIT_SUCCESS;
}
-static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
+static int loose_parse_oid(git_reference *ref, git_fbuffer *file_content)
{
int error;
reference_oid *ref_oid;
@@ -289,30 +286,30 @@ static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
static git_rtype loose_guess_rtype(const char *full_path)
{
- gitfo_buf ref_file = GITFO_BUF_INIT;
+ git_fbuffer ref_file = GIT_FBUFFER_INIT;
git_rtype type;
type = GIT_REF_INVALID;
- if (gitfo_read_file(&ref_file, full_path) == GIT_SUCCESS) {
+ if (git_futils_readbuffer(&ref_file, full_path) == GIT_SUCCESS) {
if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0)
type = GIT_REF_SYMBOLIC;
else
type = GIT_REF_OID;
}
- gitfo_free_buf(&ref_file);
+ git_futils_freebuffer(&ref_file);
return type;
}
static int loose_lookup(
- git_reference **ref_out,
- git_repository *repo,
+ git_reference **ref_out,
+ git_repository *repo,
const char *name,
int skip_symbolic)
{
int error = GIT_SUCCESS;
- gitfo_buf ref_file = GITFO_BUF_INIT;
+ git_fbuffer ref_file = GIT_FBUFFER_INIT;
git_reference *ref = NULL;
time_t ref_time;
@@ -344,11 +341,11 @@ static int loose_lookup(
ref->mtime = ref_time;
*ref_out = ref;
- gitfo_free_buf(&ref_file);
+ git_futils_freebuffer(&ref_file);
return GIT_SUCCESS;
cleanup:
- gitfo_free_buf(&ref_file);
+ git_futils_freebuffer(&ref_file);
reference_free(ref);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to lookup loose reference");
}
@@ -360,9 +357,7 @@ static int loose_write(git_reference *ref)
int error;
struct stat st;
- assert((ref->type & GIT_REF_PACKED) == 0);
-
- git__joinpath(ref_path, ref->owner->path_repository, ref->name);
+ git_path_join(ref_path, ref->owner->path_repository, ref->name);
if ((error = git_filebuf_open(&file, ref_path, GIT_FILEBUF_FORCE)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write loose reference");
@@ -389,7 +384,7 @@ static int loose_write(git_reference *ref)
error = git_filebuf_commit(&file);
- if (gitfo_stat(ref_path, &st) == GIT_SUCCESS)
+ if (p_stat(ref_path, &st) == GIT_SUCCESS)
ref->mtime = st.st_mtime;
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write loose reference");
@@ -410,7 +405,7 @@ unlock:
static int packed_parse_peel(
reference_oid *tag_ref,
- const char **buffer_out,
+ const char **buffer_out,
const char *buffer_end)
{
const char *buffer = *buffer_out + 1;
@@ -506,7 +501,7 @@ cleanup:
static int packed_load(git_repository *repo)
{
int error = GIT_SUCCESS;
- gitfo_buf packfile = GITFO_BUF_INIT;
+ git_fbuffer packfile = GIT_FBUFFER_INIT;
const char *buffer_start, *buffer_end;
git_refcache *ref_cache = &repo->references;
@@ -530,7 +525,7 @@ static int packed_load(git_repository *repo)
git_hashtable_clear(repo->references.packfile);
} else {
ref_cache->packfile = git_hashtable_alloc(
- default_table_size,
+ default_table_size,
reftable_hash,
(git_hash_keyeq_ptr)strcmp);
@@ -585,13 +580,13 @@ static int packed_load(git_repository *repo)
}
}
- gitfo_free_buf(&packfile);
+ git_futils_freebuffer(&packfile);
return GIT_SUCCESS;
cleanup:
git_hashtable_free(ref_cache->packfile);
ref_cache->packfile = NULL;
- gitfo_free_buf(&packfile);
+ git_futils_freebuffer(&packfile);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to load packed references");
}
@@ -612,8 +607,8 @@ static int _dirent_loose_listall(void *_data, char *full_path)
struct dirent_list_data *data = (struct dirent_list_data *)_data;
char *file_path = full_path + data->repo_path_len;
- if (gitfo_isdir(full_path) == GIT_SUCCESS)
- return gitfo_dirent(full_path, GIT_PATH_MAX, _dirent_loose_listall, _data);
+ if (git_futils_isdir(full_path) == GIT_SUCCESS)
+ return git_futils_direach(full_path, GIT_PATH_MAX, _dirent_loose_listall, _data);
/* do not add twice a reference that exists already in the packfile */
if ((data->list_flags & GIT_REF_PACKED) != 0 &&
@@ -635,8 +630,8 @@ static int _dirent_loose_load(void *data, char *full_path)
char *file_path;
int error;
- if (gitfo_isdir(full_path) == GIT_SUCCESS)
- return gitfo_dirent(full_path, GIT_PATH_MAX, _dirent_loose_load, repository);
+ if (git_futils_isdir(full_path) == GIT_SUCCESS)
+ return git_futils_direach(full_path, GIT_PATH_MAX, _dirent_loose_load, repository);
file_path = full_path + strlen(repository->path_repository);
error = loose_lookup(&reference, repository, file_path, 1);
@@ -668,7 +663,7 @@ static int packed_loadloose(git_repository *repository)
/* the packfile must have been previously loaded! */
assert(repository->references.packfile);
- git__joinpath(refs_path, repository->path_repository, GIT_REFS_DIR);
+ git_path_join(refs_path, repository->path_repository, GIT_REFS_DIR);
/* Remove any loose references from the cache */
{
@@ -685,9 +680,9 @@ static int packed_loadloose(git_repository *repository)
/*
* Load all the loose files from disk into the Packfile table.
* This will overwrite any old packed entries with their
- * updated loose versions
+ * updated loose versions
*/
- return gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_load, repository);
+ return git_futils_direach(refs_path, GIT_PATH_MAX, _dirent_loose_load, repository);
}
/*
@@ -701,7 +696,7 @@ static int packed_write_ref(reference_oid *ref, git_filebuf *file)
git_oid_fmt(oid, &ref->oid);
oid[GIT_OID_HEXSZ] = 0;
- /*
+ /*
* For references that peel to an object in the repo, we must
* write the resulting peel on a separate line, e.g.
*
@@ -727,7 +722,7 @@ static int packed_write_ref(reference_oid *ref, git_filebuf *file)
/*
* Find out what object this reference resolves to.
*
- * For references that point to a 'big' tag (e.g. an
+ * For references that point to a 'big' tag (e.g. an
* actual tag object on the repository), we need to
* cache on the packfile the OID of the object to
* which that 'big tag' is pointing to.
@@ -808,10 +803,10 @@ static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
if (reference != NULL)
continue;
- git__joinpath(full_path, repo->path_repository, ref->name);
+ git_path_join(full_path, repo->path_repository, ref->name);
- if (gitfo_exists(full_path) == GIT_SUCCESS &&
- gitfo_unlink(full_path) < GIT_SUCCESS)
+ if (git_futils_exists(full_path) == GIT_SUCCESS &&
+ p_unlink(full_path) < GIT_SUCCESS)
error = GIT_EOSERR;
/*
@@ -869,7 +864,7 @@ static int packed_write(git_repository *repo)
git_vector_sort(&packing_list);
/* Now we can open the file! */
- git__joinpath(pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE);
+ git_path_join(pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE);
if ((error = git_filebuf_open(&pack_file, pack_file_path, 0)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write packed reference");
@@ -909,7 +904,7 @@ cleanup:
error = packed_remove_loose(repo, &packing_list);
- if (gitfo_stat(pack_file_path, &st) == GIT_SUCCESS)
+ if (p_stat(pack_file_path, &st) == GIT_SUCCESS)
repo->references.packfile_time = st.st_mtime;
}
}
@@ -920,117 +915,6 @@ cleanup:
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write packed reference");
}
-/*****************************************
- * Internal methods - reference creation
- *****************************************/
-
-static int reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target, int force)
-{
- char normalized[GIT_REFNAME_MAX];
- int error = GIT_SUCCESS, updated = 0;
- git_reference *ref = NULL, *old_ref = NULL;
-
- if (git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force)
- return git__throw(GIT_EEXISTS, "Failed to create symbolic reference. Reference already exists");
-
- /*
- * If they old ref was of the same type, then we can just update
- * it (once we've checked that the target is valid). Otherwise we
- * need a new reference because we can't make a symbolic ref out
- * of an oid one.
- * If if didn't exist, then we need to create a new one anyway.
- */
- if (ref && ref->type & GIT_REF_SYMBOLIC){
- updated = 1;
- } else {
- ref = NULL;
- error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC);
- if (error < GIT_SUCCESS)
- goto cleanup;
- }
-
- /* The target can aither be the name of an object id reference or the name of another symbolic reference */
- error = normalize_name(normalized, sizeof(normalized), target, 0);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- /* set the target; this will write the reference on disk */
- error = git_reference_set_target(ref, normalized);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- /*
- * If we didn't update the ref, then we need to insert or replace
- * it in the loose cache. If we replaced a ref, free it.
- */
- if (!updated){
- error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, (void **) &old_ref);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- if(old_ref)
- reference_free(old_ref);
- }
-
- *ref_out = ref;
-
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference");
-
-cleanup:
- reference_free(ref);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference");
-}
-
-static int reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id, int force)
-{
- int error = GIT_SUCCESS, updated = 0;
- git_reference *ref = NULL, *old_ref = NULL;
-
- if(git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force)
- return git__throw(GIT_EEXISTS, "Failed to create reference OID. Reference already exists");
-
- if ((error = reference_available(repo, name, NULL)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to create reference");
-
- /*
- * If they old ref was of the same type, then we can just update
- * it (once we've checked that the target is valid). Otherwise we
- * need a new reference because we can't make a symbolic ref out
- * of an oid one.
- * If if didn't exist, then we need to create a new one anyway.
- */
- if (ref && ref-> type & GIT_REF_OID){
- updated = 1;
- } else {
- ref = NULL;
- error = reference_create(&ref, repo, name, GIT_REF_OID);
- if (error < GIT_SUCCESS)
- goto cleanup;
- }
-
- /* set the oid; this will write the reference on disk */
- error = git_reference_set_oid(ref, id);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- if(!updated){
- error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, (void **) &old_ref);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- if(old_ref)
- reference_free(old_ref);
- }
-
- *ref_out = ref;
-
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID");
-
-cleanup:
- reference_free(ref);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID");
-}
-
static int _reference_available_cb(const char *ref, void *data)
{
const char *new, *old;
@@ -1075,137 +959,6 @@ static int reference_available(git_repository *repo, const char *ref, const char
return error == GIT_SUCCESS ? GIT_SUCCESS : git__throw(GIT_EEXISTS, "Reference name `%s` conflicts with existing reference", ref);
}
-/*
- * Rename a reference
- *
- * If the reference is packed, we need to rewrite the
- * packfile to remove the reference from it and create
- * the reference back as a loose one.
- *
- * If the reference is loose, we just rename it on
- * the filesystem.
- *
- * We also need to re-insert the reference on its corresponding
- * in-memory cache, since the caches are indexed by refname.
- */
-static int reference_rename(git_reference *ref, const char *new_name, int force)
-{
- int error;
- char *old_name;
- char old_path[GIT_PATH_MAX], new_path[GIT_PATH_MAX], normalized_name[GIT_REFNAME_MAX];
- git_reference *looked_up_ref, *old_ref = NULL;
-
- assert(ref);
-
- /* Ensure the name is valid */
- error = normalize_name(normalized_name, sizeof(normalized_name), new_name, ref->type & GIT_REF_OID);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to rename reference");
-
- new_name = normalized_name;
-
- /* Ensure we're not going to overwrite an existing reference
- unless the user has allowed us */
- error = git_reference_lookup(&looked_up_ref, ref->owner, new_name);
- if (error == GIT_SUCCESS && !force)
- return git__throw(GIT_EEXISTS, "Failed to rename reference. Reference already exists");
-
- if (error < GIT_SUCCESS &&
- error != GIT_ENOTFOUND)
- return git__rethrow(error, "Failed to rename reference");
-
- if ((error = reference_available(ref->owner, new_name, ref->name)) < GIT_SUCCESS)
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference. Reference already exists");
-
- old_name = ref->name;
- ref->name = git__strdup(new_name);
-
- if (ref->name == NULL) {
- ref->name = old_name;
- return GIT_ENOMEM;
- }
-
- if (ref->type & GIT_REF_PACKED) {
- /* write the packfile to disk; note
- * that the state of the in-memory cache is not
- * consistent, because the reference is indexed
- * by its old name but it already has the new one.
- * This doesn't affect writing, though, and allows
- * us to rollback if writing fails
- */
-
- ref->type &= ~GIT_REF_PACKED;
-
- /* Create the loose ref under its new name */
- error = loose_write(ref);
- if (error < GIT_SUCCESS) {
- ref->type |= GIT_REF_PACKED;
- goto cleanup;
- }
-
- /* Remove from the packfile cache in order to avoid packing it back
- * Note : we do not rely on git_reference_delete() because this would
- * invalidate the reference.
- */
- git_hashtable_remove(ref->owner->references.packfile, old_name);
-
- /* Recreate the packed-refs file without the reference */
- error = packed_write(ref->owner);
- if (error < GIT_SUCCESS)
- goto rename_loose_to_old_name;
-
- } else {
- git__joinpath(old_path, ref->owner->path_repository, old_name);
- git__joinpath(new_path, ref->owner->path_repository, ref->name);
-
- error = gitfo_mv_force(old_path, new_path);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- /* Once succesfully renamed, remove from the cache the reference known by its old name*/
- git_hashtable_remove(ref->owner->references.loose_cache, old_name);
- }
-
- /* Store the renamed reference into the loose ref cache */
- error = git_hashtable_insert2(ref->owner->references.loose_cache, ref->name, ref, (void **) &old_ref);
-
- /* If we force-replaced, we need to free the old reference */
- if(old_ref)
- reference_free(old_ref);
-
- free(old_name);
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
-
-cleanup:
- /* restore the old name if this failed */
- free(ref->name);
- ref->name = old_name;
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
-
-rename_loose_to_old_name:
- /* If we hit this point. Something *bad* happened! Think "Ghostbusters
- * crossing the streams" definition of bad.
- * Either the packed-refs has been correctly generated and something else
- * has gone wrong, or the writing of the new packed-refs has failed, and
- * we're stuck with the old one. As a loose ref always takes priority over
- * a packed ref, we'll eventually try and rename the generated loose ref to
- * its former name. It even that fails, well... we might have lost the reference
- * for good. :-/
- */
-
- git__joinpath(old_path, ref->owner->path_repository, ref->name);
- git__joinpath(new_path, ref->owner->path_repository, old_name);
-
- /* No error checking. We'll return the initial error */
- gitfo_mv_force(old_path, new_path);
-
- /* restore the old name */
- free(ref->name);
- ref->name = old_name;
-
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
-}
-
/*****************************************
* External Library API
*****************************************/
@@ -1245,7 +998,7 @@ int git_reference_lookup(git_reference **ref_out, git_repository *repo, const ch
/*
* If we cannot find a loose reference, we look into the packfile
- * Load the packfile first if it hasn't been loaded
+ * Load the packfile first if it hasn't been loaded
*/
/* load all the packed references */
error = packed_load(repo);
@@ -1261,26 +1014,6 @@ int git_reference_lookup(git_reference **ref_out, git_repository *repo, const ch
return git__throw(GIT_ENOTFOUND, "Failed to lookup reference. Reference doesn't exist");
}
-int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target)
-{
- return reference_create_symbolic(ref_out, repo, name, target, 0);
-}
-
-int git_reference_create_symbolic_f(git_reference **ref_out, git_repository *repo, const char *name, const char *target)
-{
- return reference_create_symbolic(ref_out, repo, name, target, 1);
-}
-
-int git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id)
-{
- return reference_create_oid(ref_out, repo, name, id, 0);
-}
-
-int git_reference_create_oid_f(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id)
-{
- return reference_create_oid(ref_out, repo, name, id, 1);
-}
-
/**
* Getters
*/
@@ -1335,6 +1068,113 @@ const char *git_reference_target(git_reference *ref)
return ((reference_symbolic *)ref)->target;
}
+int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target, int force)
+{
+ char normalized[GIT_REFNAME_MAX];
+ int error = GIT_SUCCESS, updated = 0;
+ git_reference *ref = NULL, *old_ref = NULL;
+
+ if (git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force)
+ return git__throw(GIT_EEXISTS, "Failed to create symbolic reference. Reference already exists");
+
+ /*
+ * If they old ref was of the same type, then we can just update
+ * it (once we've checked that the target is valid). Otherwise we
+ * need a new reference because we can't make a symbolic ref out
+ * of an oid one.
+ * If if didn't exist, then we need to create a new one anyway.
+ */
+ if (ref && ref->type & GIT_REF_SYMBOLIC){
+ updated = 1;
+ } else {
+ ref = NULL;
+ error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+ }
+
+ /* The target can aither be the name of an object id reference or the name of another symbolic reference */
+ error = normalize_name(normalized, sizeof(normalized), target, 0);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ /* set the target; this will write the reference on disk */
+ error = git_reference_set_target(ref, normalized);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ /*
+ * If we didn't update the ref, then we need to insert or replace
+ * it in the loose cache. If we replaced a ref, free it.
+ */
+ if (!updated){
+ error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, (void **) &old_ref);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ if(old_ref)
+ reference_free(old_ref);
+ }
+
+ *ref_out = ref;
+
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference");
+
+cleanup:
+ reference_free(ref);
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference");
+}
+
+int git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id, int force)
+{
+ int error = GIT_SUCCESS, updated = 0;
+ git_reference *ref = NULL, *old_ref = NULL;
+
+ if(git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force)
+ return git__throw(GIT_EEXISTS, "Failed to create reference OID. Reference already exists");
+
+ if ((error = reference_available(repo, name, NULL)) < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to create reference");
+
+ /*
+ * If they old ref was of the same type, then we can just update
+ * it (once we've checked that the target is valid). Otherwise we
+ * need a new reference because we can't make a symbolic ref out
+ * of an oid one.
+ * If if didn't exist, then we need to create a new one anyway.
+ */
+ if (ref && ref-> type & GIT_REF_OID){
+ updated = 1;
+ } else {
+ ref = NULL;
+ error = reference_create(&ref, repo, name, GIT_REF_OID);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+ }
+
+ /* set the oid; this will write the reference on disk */
+ error = git_reference_set_oid(ref, id);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ if(!updated){
+ error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, (void **) &old_ref);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ if(old_ref)
+ reference_free(old_ref);
+ }
+
+ *ref_out = ref;
+
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID");
+
+cleanup:
+ reference_free(ref);
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID");
+}
+
/**
* Setters
*/
@@ -1394,7 +1234,7 @@ int git_reference_set_oid(git_reference *ref, const git_oid *id)
git_oid_cpy(&ref_oid->oid, id);
ref->type &= ~GIT_REF_HAS_PEEL;
- error = loose_write(ref);
+ error = loose_write(ref);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -1448,6 +1288,138 @@ int git_reference_set_target(git_reference *ref, const char *target)
*/
/*
+ * Rename a reference
+ *
+ * If the reference is packed, we need to rewrite the
+ * packfile to remove the reference from it and create
+ * the reference back as a loose one.
+ *
+ * If the reference is loose, we just rename it on
+ * the filesystem.
+ *
+ * We also need to re-insert the reference on its corresponding
+ * in-memory cache, since the caches are indexed by refname.
+ */
+int git_reference_rename(git_reference *ref, const char *new_name, int force)
+{
+ int error;
+ char *old_name;
+ char old_path[GIT_PATH_MAX], new_path[GIT_PATH_MAX], normalized_name[GIT_REFNAME_MAX];
+ git_reference *looked_up_ref, *old_ref = NULL;
+
+ assert(ref);
+
+ /* Ensure the name is valid */
+ error = normalize_name(normalized_name, sizeof(normalized_name), new_name, ref->type & GIT_REF_OID);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to rename reference");
+
+ new_name = normalized_name;
+
+ /* Ensure we're not going to overwrite an existing reference
+ unless the user has allowed us */
+ error = git_reference_lookup(&looked_up_ref, ref->owner, new_name);
+ if (error == GIT_SUCCESS && !force)
+ return git__throw(GIT_EEXISTS, "Failed to rename reference. Reference already exists");
+
+ if (error < GIT_SUCCESS &&
+ error != GIT_ENOTFOUND)
+ return git__rethrow(error, "Failed to rename reference");
+
+ if ((error = reference_available(ref->owner, new_name, ref->name)) < GIT_SUCCESS)
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference. Reference already exists");
+
+ old_name = ref->name;
+ ref->name = git__strdup(new_name);
+
+ if (ref->name == NULL) {
+ ref->name = old_name;
+ return GIT_ENOMEM;
+ }
+
+ if (ref->type & GIT_REF_PACKED) {
+ /* write the packfile to disk; note
+ * that the state of the in-memory cache is not
+ * consistent, because the reference is indexed
+ * by its old name but it already has the new one.
+ * This doesn't affect writing, though, and allows
+ * us to rollback if writing fails
+ */
+
+ /* Create the loose ref under its new name */
+ error = loose_write(ref);
+ if (error < GIT_SUCCESS) {
+ ref->type |= GIT_REF_PACKED;
+ goto cleanup;
+ }
+
+ ref->type &= ~GIT_REF_PACKED;
+
+ /* Remove from the packfile cache in order to avoid packing it back
+ * Note : we do not rely on git_reference_delete() because this would
+ * invalidate the reference.
+ */
+ git_hashtable_remove(ref->owner->references.packfile, old_name);
+
+ /* Recreate the packed-refs file without the reference */
+ error = packed_write(ref->owner);
+ if (error < GIT_SUCCESS)
+ goto rename_loose_to_old_name;
+
+ } else {
+ git_path_join(old_path, ref->owner->path_repository, old_name);
+ git_path_join(new_path, ref->owner->path_repository, ref->name);
+
+ error = git_futils_mv_withpath(old_path, new_path);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ /* Once succesfully renamed, remove from the cache the reference known by its old name*/
+ git_hashtable_remove(ref->owner->references.loose_cache, old_name);
+ }
+
+ /* Store the renamed reference into the loose ref cache */
+ error = git_hashtable_insert2(ref->owner->references.loose_cache, ref->name, ref, (void **) &old_ref);
+
+ /* If we force-replaced, we need to free the old reference */
+ if(old_ref)
+ reference_free(old_ref);
+
+ free(old_name);
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
+
+cleanup:
+ /* restore the old name if this failed */
+ free(ref->name);
+ ref->name = old_name;
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
+
+rename_loose_to_old_name:
+ /* If we hit this point. Something *bad* happened! Think "Ghostbusters
+ * crossing the streams" definition of bad.
+ * Either the packed-refs has been correctly generated and something else
+ * has gone wrong, or the writing of the new packed-refs has failed, and
+ * we're stuck with the old one. As a loose ref always takes priority over
+ * a packed ref, we'll eventually try and rename the generated loose ref to
+ * its former name. It even that fails, well... we might have lost the reference
+ * for good. :-/
+ */
+
+ git_path_join(old_path, ref->owner->path_repository, ref->name);
+ git_path_join(new_path, ref->owner->path_repository, old_name);
+
+ /* No error checking. We'll return the initial error */
+ git_futils_mv_withpath(old_path, new_path);
+
+ /* restore the old name */
+ free(ref->name);
+ ref->name = old_name;
+
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
+}
+
+
+/*
* Delete a reference.
*
* If the reference is packed, this is an expensive
@@ -1473,16 +1445,16 @@ int git_reference_delete(git_reference *ref)
/* load the existing packfile */
if ((error = packed_load(ref->owner)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to delete reference");
-
+
if (git_hashtable_remove(ref->owner->references.packfile, ref->name) < GIT_SUCCESS)
return git__throw(GIT_ENOTFOUND, "Reference not found");
error = packed_write(ref->owner);
} else {
char full_path[GIT_PATH_MAX];
- git__joinpath(full_path, ref->owner->path_repository, ref->name);
+ git_path_join(full_path, ref->owner->path_repository, ref->name);
git_hashtable_remove(ref->owner->references.loose_cache, ref->name);
- error = gitfo_unlink(full_path);
+ error = p_unlink(full_path);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -1500,16 +1472,6 @@ cleanup:
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to delete reference");
}
-int git_reference_rename(git_reference *ref, const char *new_name)
-{
- return reference_rename(ref, new_name, 0);
-}
-
-int git_reference_rename_f(git_reference *ref, const char *new_name)
-{
- return reference_rename(ref, new_name, 1);
-}
-
int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
{
git_repository *repo;
@@ -1520,7 +1482,7 @@ int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
if ((error = loose_update(ref)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to resolve reference");
-
+
repo = ref->owner;
for (i = 0; i < MAX_NESTING_LEVEL; ++i) {
@@ -1585,8 +1547,8 @@ int git_reference_foreach(git_repository *repo, unsigned int list_flags, int (*c
data.callback_payload = payload;
- git__joinpath(refs_path, repo->path_repository, GIT_REFS_DIR);
- return gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
+ git_path_join(refs_path, repo->path_repository, GIT_REFS_DIR);
+ return git_futils_direach(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
}
int cb__reflist_add(const char *ref, void *data)
diff --git a/src/repository.c b/src/repository.c
index 1fef73907..843582433 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -39,15 +39,9 @@
#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
#define GIT_FILE_CONTENT_PREFIX "gitdir: "
-#define GIT_FILE_CONTENT_PREFIX_LENGTH 8
#define GIT_BRANCH_MASTER "master"
-typedef struct {
- char *path_repository;
- unsigned is_bare:1, has_been_reinit:1;
-} repo_init;
-
/*
* Git repository open methods
*
@@ -68,7 +62,7 @@ static int assign_repository_dirs(
if (git_dir == NULL)
return git__throw(GIT_ENOTFOUND, "Failed to open repository. Git dir not found");
- error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_dir, NULL);
+ error = git_path_prettify_dir(path_aux, git_dir, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open repository");
@@ -79,9 +73,9 @@ static int assign_repository_dirs(
/* path to GIT_OBJECT_DIRECTORY */
if (git_object_directory == NULL)
- git__joinpath(path_aux, repo->path_repository, GIT_OBJECTS_DIR);
+ git_path_join(path_aux, repo->path_repository, GIT_OBJECTS_DIR);
else {
- error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_object_directory, NULL);
+ error = git_path_prettify_dir(path_aux, git_object_directory, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open repository");
}
@@ -95,7 +89,7 @@ static int assign_repository_dirs(
if (git_work_tree == NULL)
repo->is_bare = 1;
else {
- error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_work_tree, NULL);
+ error = git_path_prettify_dir(path_aux, git_work_tree, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open repository");
@@ -106,9 +100,9 @@ static int assign_repository_dirs(
/* Path to GIT_INDEX_FILE */
if (git_index_file == NULL)
- git__joinpath(path_aux, repo->path_repository, GIT_INDEX_FILE);
+ git_path_join(path_aux, repo->path_repository, GIT_INDEX_FILE);
else {
- error = gitfo_prettify_file_path(path_aux, sizeof(path_aux), git_index_file, NULL);
+ error = git_path_prettify(path_aux, git_index_file, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open repository");
}
@@ -118,7 +112,7 @@ static int assign_repository_dirs(
if (repo->path_index == NULL)
return GIT_ENOMEM;
}
-
+
return GIT_SUCCESS;
}
@@ -126,16 +120,16 @@ static int check_repository_dirs(git_repository *repo)
{
char path_aux[GIT_PATH_MAX];
- if (gitfo_isdir(repo->path_repository) < GIT_SUCCESS)
+ if (git_futils_isdir(repo->path_repository) < GIT_SUCCESS)
return git__throw(GIT_ENOTAREPO, "`%s` is not a folder", repo->path_repository);
/* Ensure GIT_OBJECT_DIRECTORY exists */
- if (gitfo_isdir(repo->path_odb) < GIT_SUCCESS)
+ if (git_futils_isdir(repo->path_odb) < GIT_SUCCESS)
return git__throw(GIT_ENOTAREPO, "`%s` does not exist", repo->path_odb);
/* Ensure HEAD file exists */
- git__joinpath(path_aux, repo->path_repository, GIT_HEAD_FILE);
- if (gitfo_exists(path_aux) < 0)
+ git_path_join(path_aux, repo->path_repository, GIT_HEAD_FILE);
+ if (git_futils_isfile(path_aux) < 0)
return git__throw(GIT_ENOTAREPO, "HEAD file is missing");
return GIT_SUCCESS;
@@ -147,12 +141,12 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa
const char *path_work_tree = NULL;
/* Git directory name */
- if (git__basename_r(buffer, sizeof(buffer), repository_path) < 0)
+ if (git_path_basename_r(buffer, sizeof(buffer), repository_path) < 0)
return git__throw(GIT_EINVALIDPATH, "Unable to parse folder name from `%s`", repository_path);
if (strcmp(buffer, DOT_GIT) == 0) {
/* Path to working dir */
- if (git__dirname_r(buffer, sizeof(buffer), repository_path) < 0)
+ if (git_path_dirname_r(buffer, sizeof(buffer), repository_path) < 0)
return git__throw(GIT_EINVALIDPATH, "Unable to parse parent folder name from `%s`", repository_path);
path_work_tree = buffer;
}
@@ -160,6 +154,26 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa
return assign_repository_dirs(repo, repository_path, NULL, NULL, path_work_tree);
}
+static int quickcheck_repository_dir(const char *repository_path)
+{
+ char path_aux[GIT_PATH_MAX];
+
+ /* Ensure HEAD file exists */
+ git_path_join(path_aux, repository_path, GIT_HEAD_FILE);
+ if (git_futils_isfile(path_aux) < 0)
+ return GIT_ERROR;
+
+ git_path_join(path_aux, repository_path, GIT_OBJECTS_DIR);
+ if (git_futils_isdir(path_aux) < 0)
+ return GIT_ERROR;
+
+ git_path_join(path_aux, repository_path, GIT_REFS_DIR);
+ if (git_futils_isdir(path_aux) < 0)
+ return GIT_ERROR;
+
+ return GIT_SUCCESS;
+}
+
static git_repository *repository_alloc()
{
int error;
@@ -207,8 +221,8 @@ int git_repository_open3(git_repository **repo_out,
if (repo == NULL)
return GIT_ENOMEM;
- error = assign_repository_dirs(repo,
- git_dir,
+ error = assign_repository_dirs(repo,
+ git_dir,
NULL,
git_index_file,
git_work_tree);
@@ -247,7 +261,7 @@ int git_repository_open2(git_repository **repo_out,
return GIT_ENOMEM;
error = assign_repository_dirs(repo,
- git_dir,
+ git_dir,
git_object_directory,
git_index_file,
git_work_tree);
@@ -286,7 +300,7 @@ int git_repository_config(
if (error < GIT_SUCCESS)
return error;
- git__joinpath(config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
+ git_path_join(config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
error = git_config_add_file_ondisk(*out, config_path, 3);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -352,30 +366,13 @@ cleanup:
return git__rethrow(error, "Failed to open repository");
}
-static int abspath(char *buffer_out, size_t size, const char *path)
-{
- assert(buffer_out && size >= GIT_PATH_MAX);
-
- #ifdef GIT_WIN32
- if (_fullpath(buffer_out, path, size) == NULL)
- return git__throw(GIT_EOSERR, "Failed to retrieve real path: %s causing errors", buffer_out);
- #else
- if (realpath(path, buffer_out) == NULL)
- return git__throw(GIT_EOSERR, "Failed to retrieve real path: %s causing errors", buffer_out);
- #endif
-
- gitfo_posixify_path(buffer_out);
-
- return GIT_SUCCESS;
-}
-
static int retrieve_device(dev_t *device_out, const char *path)
{
struct stat path_info;
assert(device_out);
- if (gitfo_stat(path, &path_info))
+ if (p_lstat(path, &path_info))
return git__throw(GIT_EOSERR, "Failed to get file informations: %s", path);
*device_out = path_info.st_dev;
@@ -393,7 +390,7 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
assert(path);
- min_len = gitfo_retrieve_path_root_offset(path) + 1;
+ min_len = git_path_root(path) + 1;
if (ceiling_directories == NULL || min_len == 0)
return min_len;
@@ -402,13 +399,13 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
len = sep - ceil;
- if (len == 0 || len > GIT_PATH_MAX || gitfo_retrieve_path_root_offset(ceil) == -1)
+ if (len == 0 || len > GIT_PATH_MAX || git_path_root(ceil) == -1)
continue;
strncpy(buf, ceil, len);
buf[len] = '\0';
- if (abspath(buf2, sizeof(buf2), buf) < GIT_SUCCESS)
+ if (p_realpath(buf, buf2) == NULL)
continue;
len = strlen(buf2);
@@ -426,15 +423,15 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
return max_len <= min_len ? min_len : max_len;
}
-static int read_gitfile(char *path_out, size_t size, const char *file_path, const char *base_path)
+static int read_gitfile(char *path_out, const char *file_path, const char *base_path)
{
- gitfo_buf file;
+ git_fbuffer file;
int error, end_offset;
char *data;
- assert(file_path && path_out && size > 0);
+ assert(path_out && file_path && path_out);
- error = gitfo_read_file(&file, file_path);
+ error = git_futils_readbuffer(&file, file_path);
if (error < GIT_SUCCESS)
return error;
@@ -442,7 +439,7 @@ static int read_gitfile(char *path_out, size_t size, const char *file_path, cons
data = (char*)(file.data);
if (git__prefixcmp(data, GIT_FILE_CONTENT_PREFIX)) {
- gitfo_free_buf(&file);
+ git_futils_freebuffer(&file);
return git__throw(GIT_ENOTFOUND, "Invalid gitfile format `%s`", file_path);
}
@@ -451,22 +448,19 @@ static int read_gitfile(char *path_out, size_t size, const char *file_path, cons
for (;data[end_offset] == '\r' || data[end_offset] == '\n'; --end_offset);
data[end_offset + 1] = '\0';
- if (GIT_FILE_CONTENT_PREFIX_LENGTH == end_offset + 1) {
- gitfo_free_buf(&file);
+ if (STRLEN(GIT_FILE_CONTENT_PREFIX) == end_offset + 1) {
+ git_futils_freebuffer(&file);
return git__throw(GIT_ENOTFOUND, "No path in git file `%s`", file_path);
}
- error = gitfo_prettify_dir_path(path_out, size, data + GIT_FILE_CONTENT_PREFIX_LENGTH, base_path);
- if (error == GIT_SUCCESS) {
- end_offset = strlen(path_out);
-
- if (end_offset > 0 && path_out[end_offset - 1] == '/')
- path_out[end_offset - 1 ] = '\0';
- }
+ data = data + STRLEN(GIT_FILE_CONTENT_PREFIX);
+ error = git_path_prettify_dir(path_out, data, base_path);
+ git_futils_freebuffer(&file);
- gitfo_free_buf(&file);
+ if (error == 0 && git_futils_exists(path_out) == 0)
+ return GIT_SUCCESS;
- return error;
+ return git__throw(GIT_EOBJCORRUPTED, "The `.git` file points to an inexisting path");
}
static void git_repository__free_dirs(git_repository *repo)
@@ -498,7 +492,6 @@ void git_repository_free(git_repository *repo)
int git_repository_discover(char *repository_path, size_t size, const char *start_path, int across_fs, const char *ceiling_dirs)
{
- git_repository repo;
int error, ceiling_offset;
char bare_path[GIT_PATH_MAX];
char normal_path[GIT_PATH_MAX];
@@ -506,108 +499,89 @@ int git_repository_discover(char *repository_path, size_t size, const char *star
dev_t current_device = 0;
assert(start_path && repository_path);
- memset(&repo, 0x0, sizeof(git_repository));
-
- error = abspath(bare_path, sizeof(bare_path), start_path);
+ error = git_path_prettify_dir(bare_path, start_path, NULL);
if (error < GIT_SUCCESS)
- goto cleanup;
+ return error;
if (!across_fs) {
error = retrieve_device(&current_device, bare_path);
-
if (error < GIT_SUCCESS)
- goto cleanup;
+ return error;
}
ceiling_offset = retrieve_ceiling_directories_offset(bare_path, ceiling_dirs);
- git__joinpath(normal_path, bare_path, DOT_GIT);
+ git_path_join(normal_path, bare_path, DOT_GIT);
- while(1){
- //look for .git file
- if (gitfo_isfile(normal_path) == GIT_SUCCESS) {
- error = read_gitfile(repository_path, size, normal_path, bare_path);
+ while(1) {
+ /**
+ * If the `.git` file is regular instead of
+ * a directory, it should contain the path of the actual git repository
+ */
+ if (git_futils_isfile(normal_path) == GIT_SUCCESS) {
+ error = read_gitfile(repository_path, normal_path, bare_path);
- if (error < GIT_SUCCESS) {
- git__rethrow(error, "Unable to read git file `%s`", normal_path);
- goto cleanup;
- }
-
- error = discover_repository_dirs(&repo, repository_path);
if (error < GIT_SUCCESS)
- goto cleanup;
+ return git__rethrow(error, "Unable to read git file `%s`", normal_path);
- git_repository__free_dirs(&repo);
+ error = quickcheck_repository_dir(repository_path);
+ if (error < GIT_SUCCESS)
+ return git__throw(GIT_ENOTFOUND, "The `.git` file found at '%s' points"
+ "to an inexisting Git folder", normal_path);
return GIT_SUCCESS;
}
- //look for .git repository
- error = discover_repository_dirs(&repo, normal_path);
- if (error < GIT_SUCCESS && error != GIT_ENOTAREPO)
- goto cleanup;
-
- if (error == GIT_SUCCESS) {
- found_path = normal_path;
- break;
+ /**
+ * If the `.git` file is a folder, we check inside of it
+ */
+ if (git_futils_isdir(normal_path) == GIT_SUCCESS) {
+ error = quickcheck_repository_dir(normal_path);
+ if (error == GIT_SUCCESS) {
+ found_path = normal_path;
+ break;
+ }
}
- git_repository__free_dirs(&repo);
-
- //look for bare repository in current directory
- error = discover_repository_dirs(&repo, bare_path);
- if (error < GIT_SUCCESS && error != GIT_ENOTAREPO)
- goto cleanup;
-
+ /**
+ * Otherwise, the repository may be bare, let's check
+ * the root anyway
+ */
+ error = quickcheck_repository_dir(bare_path);
if (error == GIT_SUCCESS) {
found_path = bare_path;
break;
}
- git_repository__free_dirs(&repo);
-
- if (git__dirname_r(normal_path, sizeof(normal_path), bare_path) < GIT_SUCCESS)
- goto cleanup;
+ if (git_path_dirname_r(normal_path, sizeof(normal_path), bare_path) < GIT_SUCCESS)
+ return git__throw(GIT_EOSERR, "Failed to dirname '%s'", bare_path);
if (!across_fs) {
dev_t new_device;
error = retrieve_device(&new_device, normal_path);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- if (current_device != new_device) {
- error = git__throw(GIT_ENOTAREPO,"Not a git repository (or any parent up to mount parent %s)\n"
- "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM_ENVIRONMENT not set).", bare_path);
- goto cleanup;
+ if (error < GIT_SUCCESS || current_device != new_device) {
+ return git__throw(GIT_ENOTAREPO,"Not a git repository (or any parent up to mount parent %s)\n"
+ "Stopping at filesystem boundary.", bare_path);
}
current_device = new_device;
}
strcpy(bare_path, normal_path);
- git__joinpath(normal_path, bare_path, DOT_GIT);
+ git_path_join(normal_path, bare_path, DOT_GIT);
- //nothing has been found, lets try the parent directory
+ // nothing has been found, lets try the parent directory
if (bare_path[ceiling_offset] == '\0') {
- error = git__throw(GIT_ENOTAREPO,"Not a git repository (or any of the parent directories): %s", start_path);
- goto cleanup;
+ return git__throw(GIT_ENOTAREPO,"Not a git repository (or any of the parent directories): %s", start_path);
}
-
}
- if (size < (strlen(found_path) + 1) * sizeof(char)) {
- error = git__throw(GIT_EOVERFLOW, "The repository buffer is not long enough to handle the repository path `%s`", found_path);
- goto cleanup;
+ if (size < (strlen(found_path) + 2) * sizeof(char)) {
+ return git__throw(GIT_EOVERFLOW, "The repository buffer is not long enough to handle the repository path `%s`", found_path);
}
- strcpy(repository_path, found_path);
- git_repository__free_dirs(&repo);
-
+ git_path_join(repository_path, found_path, "");
return GIT_SUCCESS;
-
- cleanup:
- git_repository__free_dirs(&repo);
- return git__rethrow(error, "Failed to discover repository");
}
git_odb *git_repository_database(git_repository *repo)
@@ -616,59 +590,61 @@ git_odb *git_repository_database(git_repository *repo)
return repo->db;
}
-static int repo_init_reinit(repo_init *results)
+static int repo_init_reinit(const char *repository_path, int is_bare)
{
/* TODO: reinit the repository */
- results->has_been_reinit = 1;
- return git__throw(GIT_ENOTIMPLEMENTED, "Failed to reinitialize the repository. This feature is not yet implemented");
+ return git__throw(GIT_ENOTIMPLEMENTED,
+ "Failed to reinitialize the %srepository at '%s'. "
+ "This feature is not yet implemented",
+ is_bare ? "bare" : "", repository_path);
}
static int repo_init_createhead(git_repository *repo)
{
git_reference *head_reference;
- return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE); /* TODO: finalize moving refs.c to new error handling */
-}
-
-static int repo_init_check_head_existence(char * repository_path)
-{
- char temp_path[GIT_PATH_MAX];
-
- git__joinpath(temp_path, repository_path, GIT_HEAD_FILE);
- return gitfo_exists(temp_path);
+ return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE, 0);
}
-static int repo_init_structure(repo_init *results)
+static int repo_init_structure(const char *git_dir)
{
const int mode = 0755; /* or 0777 ? */
int error;
char temp_path[GIT_PATH_MAX];
- char *git_dir = results->path_repository;
- if (gitfo_mkdir_recurs(git_dir, mode))
+ if (git_futils_mkdir_r(git_dir, mode))
return git__throw(GIT_ERROR, "Failed to initialize repository structure. Could not mkdir");
+#ifdef GIT_WIN32
+ /* Hides the ".git" directory */
+ if (!results->is_bare) {
+ error = p_hide_directory__w32(git_dir);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to initialize repository structure");
+ }
+#endif
+
/* Creates the '/objects/info/' directory */
- git__joinpath(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
- error = gitfo_mkdir_recurs(temp_path, mode);
+ git_path_join(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
+ error = git_futils_mkdir_r(temp_path, mode);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to initialize repository structure");
/* Creates the '/objects/pack/' directory */
- git__joinpath(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
- error = gitfo_mkdir(temp_path, mode);
+ git_path_join(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
+ error = p_mkdir(temp_path, mode);
if (error < GIT_SUCCESS)
return git__throw(error, "Unable to create `%s` folder", temp_path);
/* Creates the '/refs/heads/' directory */
- git__joinpath(temp_path, git_dir, GIT_REFS_HEADS_DIR);
- error = gitfo_mkdir_recurs(temp_path, mode);
+ git_path_join(temp_path, git_dir, GIT_REFS_HEADS_DIR);
+ error = git_futils_mkdir_r(temp_path, mode);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to initialize repository structure");
/* Creates the '/refs/tags/' directory */
- git__joinpath(temp_path, git_dir, GIT_REFS_TAGS_DIR);
- error = gitfo_mkdir(temp_path, mode);
+ git_path_join(temp_path, git_dir, GIT_REFS_TAGS_DIR);
+ error = p_mkdir(temp_path, mode);
if (error < GIT_SUCCESS)
return git__throw(error, "Unable to create `%s` folder", temp_path);
@@ -677,45 +653,22 @@ static int repo_init_structure(repo_init *results)
return GIT_SUCCESS;
}
-static int repo_init_find_dir(repo_init *results, const char* path)
-{
- char temp_path[GIT_PATH_MAX];
- int error = GIT_SUCCESS;
-
- error = gitfo_prettify_dir_path(temp_path, sizeof(temp_path), path, NULL);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to find directory to initialize repository");
-
- if (!results->is_bare) {
- git__joinpath(temp_path, temp_path, GIT_DIR);
- }
-
- results->path_repository = git__strdup(temp_path);
- if (results->path_repository == NULL)
- return GIT_ENOMEM;
-
- return GIT_SUCCESS;
-}
-
int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare)
{
int error = GIT_SUCCESS;
git_repository *repo = NULL;
- repo_init results;
-
- assert(repo_out && path);
+ char repository_path[GIT_PATH_MAX];
- results.path_repository = NULL;
- results.is_bare = is_bare;
+ assert(repo_out && path);
- error = repo_init_find_dir(&results, path);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ git_path_join(repository_path, path, is_bare ? "" : GIT_DIR);
- if (!repo_init_check_head_existence(results.path_repository))
- return repo_init_reinit(&results);
+ if (git_futils_isdir(repository_path)) {
+ if (quickcheck_repository_dir(repository_path) == GIT_SUCCESS)
+ return repo_init_reinit(repository_path, is_bare);
+ }
- error = repo_init_structure(&results);
+ error = repo_init_structure(repository_path);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -725,7 +678,7 @@ int git_repository_init(git_repository **repo_out, const char *path, unsigned is
goto cleanup;
}
- error = guess_repository_dirs(repo, results.path_repository);
+ error = guess_repository_dirs(repo, repository_path);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -742,16 +695,55 @@ int git_repository_init(git_repository **repo_out, const char *path, unsigned is
/* should never fail */
assert(check_repository_dirs(repo) == GIT_SUCCESS);
- free(results.path_repository);
*repo_out = repo;
return GIT_SUCCESS;
cleanup:
- free(results.path_repository);
git_repository_free(repo);
return git__rethrow(error, "Failed to (re)init the repository `%s`", path);
}
+int git_repository_head_detached(git_repository *repo)
+{
+ git_reference *ref;
+ int error;
+ size_t GIT_UNUSED(_size);
+ git_otype type;
+
+ error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ if (git_reference_type(ref) == GIT_REF_SYMBOLIC)
+ return 0;
+
+ error = git_odb_read_header(&_size, &type, repo->db, git_reference_oid(ref));
+ if (error < GIT_SUCCESS)
+ return error;
+
+ if (type != GIT_OBJ_COMMIT)
+ return git__throw(GIT_EOBJCORRUPTED, "HEAD is not a commit");
+
+ return 1;
+}
+
+int git_repository_head_orphan(git_repository *repo)
+{
+ git_reference *ref;
+ int error;
+
+ error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ if (git_reference_type(ref) == GIT_REF_OID)
+ return 0;
+
+ error = git_reference_resolve(&ref, ref);
+
+ return error == GIT_ENOTFOUND ? 1 : error;
+}
+
int git_repository_is_empty(git_repository *repo)
{
git_reference *head, *branch;
@@ -759,12 +751,16 @@ int git_repository_is_empty(git_repository *repo)
error = git_reference_lookup(&head, repo, "HEAD");
if (error < GIT_SUCCESS)
- return git__throw(error, "Failed to determine the emptiness of the repository. An error occured while retrieving the HEAD reference");
+ return git__throw(error, "Corrupted repository. HEAD does not exist");
if (git_reference_type(head) != GIT_REF_SYMBOLIC)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to determine the emptiness of the repository. HEAD is probably in detached state");
+ return 0;
+
+ if (strcmp(git_reference_target(head), "refs/heads/master") != 0)
+ return 0;
- return git_reference_resolve(&branch, head) == GIT_SUCCESS ? 0 : 1;
+ error = git_reference_resolve(&branch, head);
+ return error == GIT_ENOTFOUND ? 1 : error;
}
const char *git_repository_path(git_repository *repo, git_repository_pathid id)
diff --git a/src/block-sha1/sha1.c b/src/sha1.c
index 8c1460102..8c1460102 100644
--- a/src/block-sha1/sha1.c
+++ b/src/sha1.c
diff --git a/src/block-sha1/sha1.h b/src/sha1.h
index 558d6aece..558d6aece 100644
--- a/src/block-sha1/sha1.h
+++ b/src/sha1.h
diff --git a/src/signature.c b/src/signature.c
index 51a2fff47..6d4860b4c 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -38,20 +38,75 @@ void git_signature_free(git_signature *sig)
free(sig);
}
+static const char *skip_leading_spaces(const char *buffer, const char *buffer_end)
+{
+ while (*buffer == ' ' && buffer < buffer_end)
+ buffer++;
+
+ return buffer;
+}
+
+static const char *skip_trailing_spaces(const char *buffer_start, const char *buffer_end)
+{
+ while (*buffer_end == ' ' && buffer_end > buffer_start)
+ buffer_end--;
+
+ return buffer_end;
+}
+
+static int process_trimming(const char *input, char **storage, const char *input_end, int fail_when_empty)
+{
+ const char *left, *right;
+ int trimmed_input_length;
+
+ left = skip_leading_spaces(input, input_end);
+ right = skip_trailing_spaces(input, input_end - 1);
+
+ if (right <= left) {
+ if (fail_when_empty)
+ return git__throw(GIT_EINVALIDARGS, "Failed to trim. Input is either empty or only contains spaces");
+ else
+ right = left - 1;
+ }
+
+ trimmed_input_length = right - left + 1;
+
+ *storage = git__malloc(trimmed_input_length + 1);
+ if (*storage == NULL)
+ return GIT_ENOMEM;
+
+ memcpy(*storage, left, trimmed_input_length);
+ (*storage)[trimmed_input_length] = 0;
+
+ return GIT_SUCCESS;
+}
+
git_signature *git_signature_new(const char *name, const char *email, git_time_t time, int offset)
{
+ int error;
git_signature *p = NULL;
+ assert(name && email);
+
if ((p = git__malloc(sizeof(git_signature))) == NULL)
goto cleanup;
- p->name = git__strdup(name);
- p->email = git__strdup(email);
- p->when.time = time;
- p->when.offset = offset;
+ memset(p, 0x0, sizeof(git_signature));
+
+ error = process_trimming(name, &p->name, name + strlen(name), 1);
+ if (error < GIT_SUCCESS) {
+ git__rethrow(GIT_EINVALIDARGS, "Failed to create signature. 'name' argument is invalid");
+ goto cleanup;
+ }
- if (p->name == NULL || p->email == NULL)
+ error = process_trimming(email, &p->email, email + strlen(email), 1);
+ if (error < GIT_SUCCESS) {
+ git__rethrow(GIT_EINVALIDARGS, "Failed to create signature. 'email' argument is invalid");
goto cleanup;
+ }
+
+ p->when.time = time;
+ p->when.offset = offset;
return p;
@@ -99,16 +154,15 @@ git_signature *git_signature_now(const char *name, const char *email)
return git_signature_new(name, email, now, (int)offset);
}
-static int parse_timezone_offset(const char *buffer, long *offset_out)
+static int parse_timezone_offset(const char *buffer, int *offset_out)
{
- long offset, dec_offset;
- int mins, hours;
+ long dec_offset;
+ int mins, hours, offset;
const char *offset_start;
const char *offset_end;
- //we are sure that *buffer == ' '
- offset_start = buffer + 1;
+ offset_start = buffer;
if (*offset_start == '\n') {
*offset_out = 0;
@@ -133,7 +187,7 @@ static int parse_timezone_offset(const char *buffer, long *offset_out)
hours = dec_offset / 100;
mins = dec_offset % 100;
- if (hours > 14) // see http://www.worldtimezone.com/faq.html
+ if (hours > 14) // see http://www.worldtimezone.com/faq.html
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Hour value too large");
if (mins > 59)
@@ -143,87 +197,120 @@ static int parse_timezone_offset(const char *buffer, long *offset_out)
if (offset_start[0] == '-')
offset *= -1;
-
+
*offset_out = offset;
return GIT_SUCCESS;
}
+int process_next_token(const char **buffer_out, char **storage,
+ const char *token_end, const char *right_boundary)
+{
+ int error = process_trimming(*buffer_out, storage, token_end, 0);
+ if (error < GIT_SUCCESS)
+ return error;
-int git_signature__parse(git_signature *sig, const char **buffer_out,
- const char *buffer_end, const char *header)
+ *buffer_out = token_end + 1;
+
+ if (*buffer_out > right_boundary)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
+
+ return GIT_SUCCESS;
+}
+
+const char *scan_for_previous_token(const char *buffer, const char *left_boundary)
{
- const size_t header_len = strlen(header);
+ const char *start;
- int name_length, email_length;
- const char *buffer = *buffer_out;
- const char *line_end, *name_end, *email_end;
- long offset = 0, time;
+ if (buffer <= left_boundary)
+ return NULL;
- memset(sig, 0x0, sizeof(git_signature));
+ start = skip_trailing_spaces(left_boundary, buffer);
- line_end = memchr(buffer, '\n', buffer_end - buffer);
- if (!line_end)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. No newline found");;
+ /* Search for previous occurence of space */
+ while (start[-1] != ' ' && start > left_boundary)
+ start--;
- if (buffer + (header_len + 1) > line_end)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
+ return start;
+}
- if (memcmp(buffer, header, header_len) != 0)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Expected prefix '%s' doesn't match actual", header);
+int parse_time(git_time_t *time_out, const char *buffer)
+{
+ long time;
+ int error;
- buffer += header_len;
+ if (*buffer == '+' || *buffer == '-')
+ return git__throw(GIT_ERROR, "Failed while parsing time. '%s' rather look like a timezone offset.", buffer);
- /* Parse name */
- if ((name_end = strstr(buffer, " <")) == NULL)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail start");
+ error = git__strtol32(&time, buffer, &buffer, 10);
- name_length = name_end - buffer;
- if (name_length <= 0)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Missing tagger name");
+ if (error < GIT_SUCCESS)
+ return error;
- sig->name = git__malloc(name_length + 1);
- if (sig->name == NULL)
- return GIT_ENOMEM;
+ *time_out = (git_time_t)time;
- memcpy(sig->name, buffer, name_length);
- sig->name[name_length] = 0;
- buffer = name_end + 2;
+ return GIT_SUCCESS;
+}
- if (buffer >= line_end)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly");
+int git_signature__parse(git_signature *sig, const char **buffer_out,
+ const char *buffer_end, const char *header)
+{
+ const char *buffer = *buffer_out;
+ const char *line_end, *name_end, *email_end, *tz_start, *time_start;
+ int error = GIT_SUCCESS;
- /* Parse email */
- if ((email_end = strstr(buffer, "> ")) == NULL)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail end");
+ memset(sig, 0x0, sizeof(git_signature));
- email_length = email_end - buffer;
- sig->email = git__malloc(email_length + 1);
- if (sig->name == NULL)
- return GIT_ENOMEM;
+ if ((line_end = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. No newline given");
+
+ if (header) {
+ const size_t header_len = strlen(header);
+
+ if (memcmp(buffer, header, header_len) != 0)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Expected prefix '%s' doesn't match actual", header);
+
+ buffer += header_len;
+ }
- memcpy(sig->email, buffer, email_length);
- sig->email[email_length] = 0;
- buffer = email_end + 2;
+ if (buffer > line_end)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
+
+ if ((name_end = strchr(buffer, '<')) == NULL)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Cannot find '<' in signature");
- if (buffer >= line_end)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly");
+ if ((email_end = strchr(buffer, '>')) == NULL)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Cannot find '>' in signature");
- /* verify email */
- if (strpbrk(sig->email, "><\n ") != NULL)
+ if (email_end < name_end)
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Malformed e-mail");
- if (git__strtol32(&time, buffer, &buffer, 10) < GIT_SUCCESS)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Timestamp isn't a number");
+ error = process_next_token(&buffer, &sig->name, name_end, line_end);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ error = process_next_token(&buffer, &sig->email, email_end, line_end);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ tz_start = scan_for_previous_token(line_end - 1, buffer);
- sig->when.time = (time_t)time;
+ if (tz_start == NULL)
+ goto clean_exit; /* No timezone nor date */
- if (parse_timezone_offset(buffer, &offset) < GIT_SUCCESS)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Could not parse timezone offset");
-
- sig->when.offset = offset;
+ time_start = scan_for_previous_token(tz_start - 1, buffer);
+ if (time_start == NULL || parse_time(&sig->when.time, time_start) < GIT_SUCCESS) {
+ /* The tz_start might point at the time */
+ parse_time(&sig->when.time, tz_start);
+ goto clean_exit;
+ }
+
+ if (parse_timezone_offset(tz_start, &sig->when.offset) < GIT_SUCCESS) {
+ sig->when.time = 0; /* Bogus timezone, we reset the time */
+ }
- *buffer_out = (line_end + 1);
+clean_exit:
+ *buffer_out = line_end + 1;
return GIT_SUCCESS;
}
@@ -236,7 +323,7 @@ int git_signature__write(char **signature, const char *header, const git_signatu
offset = sig->when.offset;
sign = (sig->when.offset < 0) ? '-' : '+';
-
+
if (offset < 0)
offset = -offset;
diff --git a/src/tag.c b/src/tag.c
index c3924a1f8..de70c50ae 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -170,7 +170,7 @@ static int retreive_tag_reference(git_reference **tag_reference_out, char *ref_n
git_reference *tag_ref;
int error;
- git__joinpath(ref_name_out, GIT_REFS_TAGS_DIR, tag_name);
+ git_path_join(ref_name_out, GIT_REFS_TAGS_DIR, tag_name);
error = git_reference_lookup(&tag_ref, repo, ref_name_out);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to retrieve tag reference");
@@ -180,52 +180,11 @@ static int retreive_tag_reference(git_reference **tag_reference_out, char *ref_n
return GIT_SUCCESS;
}
-/* tag_reference_out will contain the reference of the tag if exists, otherwise NULL */
-static int tag_valid_in_odb(
- git_reference **tag_reference_out,
- char *ref_name_out,
- const git_oid *target,
- git_otype target_type,
- git_repository *repo,
- const char *tag_name) {
-
- int error;
-
- *tag_reference_out = NULL;
-
-
- error = retreive_tag_reference(tag_reference_out, ref_name_out, repo, tag_name);
-
- switch (error) {
- case GIT_SUCCESS:
- /* Fall trough */
- case GIT_ENOTFOUND:
- break;
-
- default:
- return git__rethrow(error, "Failed to create tag");
- }
-
- if (!git_odb_exists(repo->db, target))
- return git__throw(GIT_ENOTFOUND, "Failed to create tag. Object to tag doesn't exist");
-
- /* Try to find out what the type is */
- if (target_type == GIT_OBJ_ANY) {
- size_t _unused;
- error = git_odb_read_header(&_unused, &target_type, repo->db, target);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to create tag");
- }
-
- return GIT_SUCCESS;
-}
-
-static int tag_create(
+int git_tag_create(
git_oid *oid,
git_repository *repo,
const char *tag_name,
- const git_oid *target,
- git_otype target_type,
+ const git_object *target,
const git_signature *tagger,
const char *message,
int allow_ref_overwrite)
@@ -235,20 +194,31 @@ static int tag_create(
const char *type_str;
char *tagger_str;
- git_reference *new_ref;
+ git_reference *new_ref = NULL;
char ref_name[GIT_REFNAME_MAX];
int type_str_len, tag_name_len, tagger_str_len, message_len;
int error, should_update_ref = 0;
- if ((error = tag_valid_in_odb(&new_ref, ref_name, target, target_type, repo, tag_name)) < GIT_SUCCESS)
- return git__rethrow(error, "Failed to create tag");
-
- /** Ensure the tag name doesn't conflict with an already existing
+ if (git_object_owner(target) != repo)
+ return git__throw(GIT_EINVALIDARGS, "The given target does not belong to this repository");
+
+ error = retreive_tag_reference(&new_ref, ref_name, repo, tag_name);
+
+ switch (error) {
+ case GIT_SUCCESS:
+ case GIT_ENOTFOUND:
+ break;
+
+ default:
+ return git__rethrow(error, "Failed to create tag");
+ }
+
+ /** Ensure the tag name doesn't conflict with an already existing
* reference unless overwriting has explictly been requested **/
- if(new_ref != NULL) {
- if(!allow_ref_overwrite) {
+ if (new_ref != NULL) {
+ if (!allow_ref_overwrite) {
git_oid_cpy(oid, git_reference_oid(new_ref));
return git__throw(GIT_EEXISTS, "Tag already exists");
} else {
@@ -256,8 +226,7 @@ static int tag_create(
}
}
- type_str = git_object_type2string(target_type);
-
+ type_str = git_object_type2string(git_object_type(target));
tagger_str_len = git_signature__write(&tagger_str, "tagger", tagger);
type_str_len = strlen(type_str);
@@ -273,7 +242,7 @@ static int tag_create(
if ((error = git_odb_open_wstream(&stream, repo->db, final_size, GIT_OBJ_TAG)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create tag");
- git__write_oid(stream, "object", target);
+ git__write_oid(stream, "object", git_object_id(target));
stream->write(stream, "type ", STRLEN("type "));
stream->write(stream, type_str, type_str_len);
@@ -296,121 +265,84 @@ static int tag_create(
return git__rethrow(error, "Failed to create tag");
if (!should_update_ref)
- error = git_reference_create_oid(&new_ref, repo, ref_name, oid);
+ error = git_reference_create_oid(&new_ref, repo, ref_name, oid, 0);
else
error = git_reference_set_oid(new_ref, oid);
-
+
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create tag");
}
-int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *buffer)
+int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *buffer, int allow_ref_overwrite)
{
git_tag tag;
- int error;
+ int error, should_update_ref = 0;
git_odb_stream *stream;
-
+ git_odb_object *target_obj;
+
git_reference *new_ref;
char ref_name[GIT_REFNAME_MAX];
-
+
assert(oid && buffer);
-
+
memset(&tag, 0, sizeof(tag));
-
+
/* validate the buffer */
-
if ((error = parse_tag_buffer(&tag, buffer, buffer + strlen(buffer))) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create tag");
-
- if ((error = tag_valid_in_odb(&new_ref, ref_name, &tag.target, tag.type, repo, tag.tag_name)) < GIT_SUCCESS)
+
+ /* validate the target */
+ if ((error = git_odb_read(&target_obj, repo->db, &tag.target)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create tag");
-
+
+ if (tag.type != target_obj->raw.type)
+ return git__throw(error, "The type for the given target is invalid");
+
+ git_odb_object_close(target_obj);
+
+ error = retreive_tag_reference(&new_ref, ref_name, repo, tag.tag_name);
+
+ switch (error) {
+ case GIT_SUCCESS:
+ case GIT_ENOTFOUND:
+ break;
+
+ default:
+ return git__rethrow(error, "Failed to create tag");
+ }
+
+ /** Ensure the tag name doesn't conflict with an already existing
+ * reference unless overwriting has explictly been requested **/
if (new_ref != NULL) {
- git_oid_cpy(oid, git_reference_oid(new_ref));
- return git__throw(GIT_EEXISTS, "Tag already exists");
+ if (!allow_ref_overwrite) {
+ git_oid_cpy(oid, git_reference_oid(new_ref));
+ return git__throw(GIT_EEXISTS, "Tag already exists");
+ } else {
+ should_update_ref = 1;
+ }
}
-
+
/* write the buffer */
if ((error = git_odb_open_wstream(&stream, repo->db, strlen(buffer), GIT_OBJ_TAG)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create tag");
-
+
stream->write(stream, buffer, strlen(buffer));
-
+
error = stream->finalize_write(oid, stream);
stream->free(stream);
-
+
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to create tag");
-
-
- error = git_reference_create_oid(&new_ref, repo, ref_name, oid);
-
+
+ if (!should_update_ref)
+ error = git_reference_create_oid(&new_ref, repo, ref_name, oid, 0);
+ else
+ error = git_reference_set_oid(new_ref, oid);
+
git_signature_free(tag.tagger);
free(tag.tag_name);
free(tag.message);
-
- return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create tag");
-}
-int git_tag_create_o(
- git_oid *oid,
- git_repository *repo,
- const char *tag_name,
- const git_object *target,
- const git_signature *tagger,
- const char *message)
-{
- return tag_create(
- oid, repo, tag_name,
- git_object_id(target),
- git_object_type(target),
- tagger, message, 0);
-}
-
-int git_tag_create(
- git_oid *oid,
- git_repository *repo,
- const char *tag_name,
- const git_oid *target,
- git_otype target_type,
- const git_signature *tagger,
- const char *message)
-{
- return tag_create(
- oid, repo, tag_name,
- target,
- target_type,
- tagger, message, 0);
-}
-
-int git_tag_create_fo(
- git_oid *oid,
- git_repository *repo,
- const char *tag_name,
- const git_object *target,
- const git_signature *tagger,
- const char *message)
-{
- return tag_create(
- oid, repo, tag_name,
- git_object_id(target),
- git_object_type(target),
- tagger, message, 1);
-}
-
-int git_tag_create_f(
- git_oid *oid,
- git_repository *repo,
- const char *tag_name,
- const git_oid *target,
- git_otype target_type,
- const git_signature *tagger,
- const char *message)
-{
- return tag_create(
- oid, repo, tag_name,
- target,
- target_type,
- tagger, message, 1);
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create tag");
}
int git_tag_delete(git_repository *repo, const char *tag_name)
diff --git a/src/tree.c b/src/tree.c
index 2c10ab8a4..51b19f535 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -34,7 +34,7 @@
#define MAX_FILEMODE_BYTES 6
static int valid_attributes(const int attributes) {
- return attributes >= 0 && attributes <= MAX_FILEMODE;
+ return attributes >= 0 && attributes <= MAX_FILEMODE;
}
int entry_search_cmp(const void *key, const void *array_member)
@@ -47,7 +47,7 @@ int entry_search_cmp(const void *key, const void *array_member)
#if 0
static int valid_attributes(const int attributes) {
- return attributes >= 0 && attributes <= MAX_FILEMODE;
+ return attributes >= 0 && attributes <= MAX_FILEMODE;
}
#endif
@@ -56,7 +56,7 @@ int entry_sort_cmp(const void *a, const void *b)
const git_tree_entry *entry_a = *(const git_tree_entry **)(a);
const git_tree_entry *entry_b = *(const git_tree_entry **)(b);
- return gitfo_cmp_path(entry_a->filename, strlen(entry_a->filename),
+ return git_futils_cmp_path(entry_a->filename, strlen(entry_a->filename),
entry_a->attr & 040000,
entry_b->filename, strlen(entry_b->filename),
entry_b->attr & 040000);
@@ -215,9 +215,9 @@ static int write_index(git_oid *oid, git_index *index, const char *base, int bas
buffer = git__malloc(size);
if (buffer == NULL)
return GIT_ENOMEM;
-
+
offset = 0;
-
+
for (nr = entry_no; nr < maxentries; ++nr) {
git_index_entry *entry = git_index_get(index, nr);
@@ -227,11 +227,11 @@ static int write_index(git_oid *oid, git_index *index, const char *base, int bas
unsigned int write_mode;
git_oid subtree_oid;
git_oid *write_oid;
-
+
/* Did we hit the end of the directory? Return how many we wrote */
if (baselen >= pathlen || memcmp(base, pathname, baselen) != 0)
break;
-
+
/* Do we have _further_ subdirectories? */
filename = pathname + baselen;
dirname = strchr(filename, '/');
@@ -254,9 +254,9 @@ static int write_index(git_oid *oid, git_index *index, const char *base, int bas
free(buffer);
return subdir_written;
}
-
+
nr = subdir_written - 1;
-
+
/* Now we need to write out the directory entry into this tree.. */
pathlen = dirname - pathname;
write_oid = &subtree_oid;
@@ -267,14 +267,14 @@ static int write_index(git_oid *oid, git_index *index, const char *base, int bas
if (offset + entrylen + 32 > size) {
size = alloc_nr(offset + entrylen + 32);
buffer = git__realloc(buffer, size);
-
+
if (buffer == NULL)
return GIT_ENOMEM;
}
offset += write_index_entry(buffer + offset, write_mode, filename, entrylen, write_oid);
}
-
+
error = git_odb_write(oid, index->repository->db, buffer, offset, GIT_OBJ_TREE);
free(buffer);
diff --git a/src/unix/map.c b/src/unix/map.c
index 9bc6178ed..5192c8e4c 100644
--- a/src/unix/map.c
+++ b/src/unix/map.c
@@ -1,10 +1,12 @@
+#include <git2/common.h>
+
+#ifndef GIT_WIN32
#include "map.h"
#include <sys/mman.h>
#include <errno.h>
-
-int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
+int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
int mprot = 0;
int mflag = 0;
@@ -46,7 +48,7 @@ int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t o
return GIT_SUCCESS;
}
-int git__munmap(git_map *map)
+int p_munmap(git_map *map)
{
assert(map != NULL);
@@ -58,4 +60,5 @@ int git__munmap(git_map *map)
return GIT_SUCCESS;
}
+#endif
diff --git a/src/unix/posix.h b/src/unix/posix.h
new file mode 100644
index 000000000..079373919
--- /dev/null
+++ b/src/unix/posix.h
@@ -0,0 +1,14 @@
+#ifndef INCLUDE_posix__w32_h__
+#define INCLUDE_posix__w32_h__
+
+#include "common.h"
+
+#define p_lstat(p,b) lstat(p,b)
+#define p_readlink(a, b, c) readlink(a, b, c)
+#define p_link(o,n) link(o, n)
+#define p_unlink(p) unlink(p)
+#define p_mkdir(p,m) mkdir(p, m)
+#define p_fsync(fd) fsync(fd)
+#define p_realpath(p, po) realpath(p, po)
+
+#endif
diff --git a/src/util.c b/src/util.c
index ecbed9012..5b8a1367c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,4 +1,3 @@
-#define GIT__NO_HIDE_MALLOC
#include <git2.h>
#include "common.h"
#include "fnmatch.h"
@@ -168,205 +167,6 @@ int git__suffixcmp(const char *str, const char *suffix)
return strcmp(str + (a - b), suffix);
}
-/*
- * Based on the Android implementation, BSD licensed.
- * Check http://android.git.kernel.org/
- */
-int git__basename_r(char *buffer, size_t bufflen, const char *path)
-{
- const char *endp, *startp;
- int len, result;
-
- /* Empty or NULL string gets treated as "." */
- if (path == NULL || *path == '\0') {
- startp = ".";
- len = 1;
- goto Exit;
- }
-
- /* Strip trailing slashes */
- endp = path + strlen(path) - 1;
- while (endp > path && *endp == '/')
- endp--;
-
- /* All slashes becomes "/" */
- if (endp == path && *endp == '/') {
- startp = "/";
- len = 1;
- goto Exit;
- }
-
- /* Find the start of the base */
- startp = endp;
- while (startp > path && *(startp - 1) != '/')
- startp--;
-
- len = endp - startp +1;
-
-Exit:
- result = len;
- if (buffer == NULL) {
- return result;
- }
- if (len > (int)bufflen-1) {
- len = (int)bufflen-1;
- result = GIT_ENOMEM;
- }
-
- if (len >= 0) {
- memmove(buffer, startp, len);
- buffer[len] = 0;
- }
- return result;
-}
-
-/*
- * Based on the Android implementation, BSD licensed.
- * Check http://android.git.kernel.org/
- */
-int git__dirname_r(char *buffer, size_t bufflen, const char *path)
-{
- const char *endp;
- int result, len;
-
- /* Empty or NULL string gets treated as "." */
- if (path == NULL || *path == '\0') {
- path = ".";
- len = 1;
- goto Exit;
- }
-
- /* Strip trailing slashes */
- endp = path + strlen(path) - 1;
- while (endp > path && *endp == '/')
- endp--;
-
- /* Find the start of the dir */
- while (endp > path && *endp != '/')
- endp--;
-
- /* Either the dir is "/" or there are no slashes */
- if (endp == path) {
- path = (*endp == '/') ? "/" : ".";
- len = 1;
- goto Exit;
- }
-
- do {
- endp--;
- } while (endp > path && *endp == '/');
-
- len = endp - path +1;
-
-Exit:
- result = len;
- if (len+1 > GIT_PATH_MAX) {
- return GIT_ENOMEM;
- }
- if (buffer == NULL)
- return result;
-
- if (len > (int)bufflen-1) {
- len = (int)bufflen-1;
- result = GIT_ENOMEM;
- }
-
- if (len >= 0) {
- memmove(buffer, path, len);
- buffer[len] = 0;
- }
- return result;
-}
-
-
-char *git__dirname(const char *path)
-{
- char *dname = NULL;
- int len;
-
- len = (path ? strlen(path) : 0) + 2;
- dname = (char *)git__malloc(len);
- if (dname == NULL)
- return NULL;
-
- if (git__dirname_r(dname, len, path) < GIT_SUCCESS) {
- free(dname);
- return NULL;
- }
-
- return dname;
-}
-
-char *git__basename(const char *path)
-{
- char *bname = NULL;
- int len;
-
- len = (path ? strlen(path) : 0) + 2;
- bname = (char *)git__malloc(len);
- if (bname == NULL)
- return NULL;
-
- if (git__basename_r(bname, len, path) < GIT_SUCCESS) {
- free(bname);
- return NULL;
- }
-
- return bname;
-}
-
-
-const char *git__topdir(const char *path)
-{
- size_t len;
- int i;
-
- assert(path);
- len = strlen(path);
-
- if (!len || path[len - 1] != '/')
- return NULL;
-
- for (i = len - 2; i >= 0; --i)
- if (path[i] == '/')
- break;
-
- return &path[i + 1];
-}
-
-void git__joinpath_n(char *buffer_out, int count, ...)
-{
- va_list ap;
- int i;
- char *buffer_start = buffer_out;
-
- va_start(ap, count);
- for (i = 0; i < count; ++i) {
- const char *path;
- int len;
-
- path = va_arg(ap, const char *);
-
- assert((i == 0) || path != buffer_start);
-
- if (i > 0 && *path == '/' && buffer_out > buffer_start && buffer_out[-1] == '/')
- path++;
-
- if (!*path)
- continue;
-
- len = strlen(path);
- memmove(buffer_out, path, len);
- buffer_out = buffer_out + len;
-
- if (i < count - 1 && buffer_out[-1] != '/')
- *buffer_out++ = '/';
- }
- va_end(ap);
-
- *buffer_out = '\0';
-}
-
char *git__strtok(char **end, const char *sep)
{
char *ptr = *end;
@@ -449,17 +249,17 @@ uint32_t git__hash(const void *key, int len, unsigned int seed)
while(len >= 4) {
uint32_t k = *(uint32_t *)data;
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
h ^= k;
data += 4;
len -= 4;
}
-
+
switch(len) {
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
@@ -472,7 +272,7 @@ uint32_t git__hash(const void *key, int len, unsigned int seed)
h ^= h >> 15;
return h;
-}
+}
#else
/*
Cross-platform version of Murmurhash3
@@ -530,5 +330,5 @@ uint32_t git__hash(const void *key, int len, uint32_t seed)
h1 ^= h1 >> 16;
return h1;
-}
+}
#endif
diff --git a/src/util.h b/src/util.h
index fdc6b85f1..0faf7f69c 100644
--- a/src/util.h
+++ b/src/util.h
@@ -8,7 +8,7 @@
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif
-/*
+/*
* Custom memory allocation wrappers
* that set error code and error message
* on allocation failure
@@ -71,63 +71,9 @@ extern int git__suffixcmp(const char *str, const char *suffix);
extern int git__strtol32(long *n, const char *buff, const char **end_buf, int base);
-/*
- * The dirname() function shall take a pointer to a character string
- * that contains a pathname, and return a pointer to a string that is a
- * pathname of the parent directory of that file. Trailing '/' characters
- * in the path are not counted as part of the path.
- *
- * If path does not contain a '/', then dirname() shall return a pointer to
- * the string ".". If path is a null pointer or points to an empty string,
- * dirname() shall return a pointer to the string "." .
- *
- * The `git__dirname` implementation is thread safe. The returned
- * string must be manually free'd.
- *
- * The `git__dirname_r` implementation expects a string allocated
- * by the user with big enough size.
- */
-extern char *git__dirname(const char *path);
-extern int git__dirname_r(char *buffer, size_t bufflen, const char *path);
-
-/*
- * This function returns the basename of the file, which is the last
- * part of its full name given by fname, with the drive letter and
- * leading directories stripped off. For example, the basename of
- * c:/foo/bar/file.ext is file.ext, and the basename of a:foo is foo.
- *
- * Trailing slashes and backslashes are significant: the basename of
- * c:/foo/bar/ is an empty string after the rightmost slash.
- *
- * The `git__basename` implementation is thread safe. The returned
- * string must be manually free'd.
- *
- * The `git__basename_r` implementation expects a string allocated
- * by the user with big enough size.
- */
-extern char *git__basename(const char *path);
-extern int git__basename_r(char *buffer, size_t bufflen, const char *path);
-
-extern const char *git__topdir(const char *path);
-
-/**
- * Join two paths together. Takes care of properly fixing the
- * middle slashes and everything
- *
- * The paths are joined together into buffer_out; this is expected
- * to be an user allocated buffer of `GIT_PATH_MAX` size
- */
-extern void git__joinpath_n(char *buffer_out, int npath, ...);
-
-GIT_INLINE(void) git__joinpath(char *buffer_out, const char *path_a, const char *path_b)
-{
- git__joinpath_n(buffer_out, 2, path_a, path_b);
-}
-
extern void git__hexdump(const char *buffer, size_t n);
extern uint32_t git__hash(const void *key, int len, uint32_t seed);
-
/** @return true if p fits into the range of a size_t */
GIT_INLINE(int) git__is_sizet(git_off_t p)
{
diff --git a/src/vector.c b/src/vector.c
index 1ddc26e3e..0451eb082 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -61,7 +61,7 @@ int git_vector_init(git_vector *v, unsigned int initial_size, git_vector_cmp cmp
v->_alloc_size = initial_size;
v->_cmp = cmp;
-
+
v->length = 0;
v->sorted = 1;
diff --git a/src/win32/fileops.c b/src/win32/fileops.c
deleted file mode 100644
index d435e706e..000000000
--- a/src/win32/fileops.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#define GIT__WIN32_NO_HIDE_FILEOPS
-#include "fileops.h"
-#include <errno.h>
-
-int git__unlink(const char *path)
-{
- chmod(path, 0666);
- return unlink(path);
-}
-
-int git__mkstemp(char *template)
-{
- char *file = mktemp(template);
- if (file == NULL)
- return -1;
- return open(file, O_RDWR | O_CREAT | O_BINARY, 0600);
-}
-
-int git__fsync(int fd)
-{
- HANDLE fh = (HANDLE)_get_osfhandle(fd);
-
- if (fh == INVALID_HANDLE_VALUE) {
- errno = EBADF;
- return -1;
- }
-
- if (!FlushFileBuffers(fh)) {
- DWORD code = GetLastError();
-
- if (code == ERROR_INVALID_HANDLE)
- errno = EINVAL;
- else
- errno = EIO;
-
- return -1;
- }
-
- return 0;
-}
-
diff --git a/src/win32/map.c b/src/win32/map.c
index c7a39fcf6..76b926490 100644
--- a/src/win32/map.c
+++ b/src/win32/map.c
@@ -16,7 +16,7 @@ static DWORD get_page_size(void)
return page_size;
}
-int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
+int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
HANDLE fh = (HANDLE)_get_osfhandle(fd);
DWORD page_size = get_page_size();
@@ -92,7 +92,7 @@ int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t o
return GIT_SUCCESS;
}
-int git__munmap(git_map *map)
+int p_munmap(git_map *map)
{
assert(map != NULL);
diff --git a/src/mingw-compat.h b/src/win32/mingw-compat.h
index 64d780b16..64d780b16 100644
--- a/src/mingw-compat.h
+++ b/src/win32/mingw-compat.h
diff --git a/src/msvc-compat.h b/src/win32/msvc-compat.h
index df3e62d11..df3e62d11 100644
--- a/src/msvc-compat.h
+++ b/src/win32/msvc-compat.h
diff --git a/src/win32/posix.c b/src/win32/posix.c
new file mode 100644
index 000000000..dfa4e1a2c
--- /dev/null
+++ b/src/win32/posix.c
@@ -0,0 +1,211 @@
+#include "posix.h"
+#include "path.h"
+#include <errno.h>
+
+int p_unlink(const char *path)
+{
+ chmod(path, 0666);
+ return unlink(path);
+}
+
+int p_fsync(int fd)
+{
+ HANDLE fh = (HANDLE)_get_osfhandle(fd);
+
+ if (fh == INVALID_HANDLE_VALUE) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (!FlushFileBuffers(fh)) {
+ DWORD code = GetLastError();
+
+ if (code == ERROR_INVALID_HANDLE)
+ errno = EINVAL;
+ else
+ errno = EIO;
+
+ return -1;
+ }
+
+ return 0;
+}
+
+GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
+{
+ long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
+ winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
+ winTime /= 10000000; /* Nano to seconds resolution */
+ return (time_t)winTime;
+}
+
+static int do_lstat(const char *file_name, struct stat *buf)
+{
+ WIN32_FILE_ATTRIBUTE_DATA fdata;
+
+ if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
+ int fMode = S_IREAD;
+
+ if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ fMode |= S_IFDIR;
+ else
+ fMode |= S_IFREG;
+
+ if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+ fMode |= S_IWRITE;
+
+ if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ fMode |= S_IFLNK;
+
+ buf->st_ino = 0;
+ buf->st_gid = 0;
+ buf->st_uid = 0;
+ buf->st_nlink = 1;
+ buf->st_mode = (mode_t)fMode;
+ buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
+ buf->st_dev = buf->st_rdev = (_getdrive() - 1);
+ buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
+ buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
+ buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
+ return GIT_SUCCESS;
+ }
+
+ switch (GetLastError()) {
+ case ERROR_ACCESS_DENIED:
+ case ERROR_SHARING_VIOLATION:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_SHARING_BUFFER_EXCEEDED:
+ return GIT_EOSERR;
+
+ case ERROR_BUFFER_OVERFLOW:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ return GIT_ENOMEM;
+
+ default:
+ return GIT_EINVALIDPATH;
+ }
+}
+
+int p_lstat(const char *file_name, struct stat *buf)
+{
+ int namelen, error;
+ char alt_name[GIT_PATH_MAX];
+
+ if ((error = do_lstat(file_name, buf)) == GIT_SUCCESS)
+ return GIT_SUCCESS;
+
+ /* if file_name ended in a '/', Windows returned ENOENT;
+ * try again without trailing slashes
+ */
+ if (error != GIT_EINVALIDPATH)
+ return git__throw(GIT_EOSERR, "Failed to lstat file");
+
+ namelen = strlen(file_name);
+ if (namelen && file_name[namelen-1] != '/')
+ return git__throw(GIT_EOSERR, "Failed to lstat file");
+
+ while (namelen && file_name[namelen-1] == '/')
+ --namelen;
+
+ if (!namelen || namelen >= GIT_PATH_MAX)
+ return git__throw(GIT_ENOMEM, "Failed to lstat file");
+
+ memcpy(alt_name, file_name, namelen);
+ alt_name[namelen] = 0;
+ return do_lstat(alt_name, buf);
+}
+
+int p_readlink(const char *link, char *target, size_t target_len)
+{
+ typedef DWORD (WINAPI *fpath_func)(HANDLE, LPTSTR, DWORD, DWORD);
+ static fpath_func pGetFinalPath = NULL;
+ HANDLE hFile;
+ DWORD dwRet;
+
+ /*
+ * Try to load the pointer to pGetFinalPath dynamically, because
+ * it is not available in platforms older than Vista
+ */
+ if (pGetFinalPath == NULL) {
+ HINSTANCE library = LoadLibrary("kernel32");
+
+ if (library != NULL)
+ pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleA");
+
+ if (pGetFinalPath == NULL)
+ return git__throw(GIT_EOSERR,
+ "'GetFinalPathNameByHandleA' is not available in this platform");
+ }
+
+ hFile = CreateFile(link, // file to open
+ GENERIC_READ, // open for reading
+ FILE_SHARE_READ, // share for reading
+ NULL, // default security
+ OPEN_EXISTING, // existing file only
+ FILE_FLAG_BACKUP_SEMANTICS, // normal file
+ NULL); // no attr. template
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return GIT_EOSERR;
+
+ dwRet = pGetFinalPath(hFile, target, target_len, 0x0);
+ if (dwRet >= target_len)
+ return GIT_ENOMEM;
+
+ CloseHandle(hFile);
+
+ if (dwRet > 4) {
+ /* Skip first 4 characters if they are "\\?\" */
+ if (target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') {
+ char tmp[GIT_PATH_MAX];
+ unsigned int offset = 4;
+ dwRet -= 4;
+
+ /* \??\UNC\ */
+ if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') {
+ offset += 2;
+ dwRet -= 2;
+ target[offset] = '\\';
+ }
+
+ memcpy(tmp, target + offset, dwRet);
+ memcpy(target, tmp, dwRet);
+ }
+ }
+
+ target[dwRet] = '\0';
+ return dwRet;
+}
+
+int p_hide_directory__w32(const char *path)
+{
+ int error;
+
+ error = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) != 0 ?
+ GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
+
+ if (error < GIT_SUCCESS)
+ error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path);
+
+ return error;
+}
+
+char *p_realpath(const char *orig_path, char *buffer)
+{
+ int ret, alloc = 0;
+
+ if (buffer == NULL) {
+ buffer = (char *)git__malloc(GIT_PATH_MAX);
+ alloc = 1;
+ }
+
+ ret = GetFullPathName(orig_path, GIT_PATH_MAX, buffer, NULL);
+ if (!ret || ret > GIT_PATH_MAX) {
+ if (alloc) free(buffer);
+ return NULL;
+ }
+
+ git_path_mkposix(buffer);
+ return buffer;
+}
+
diff --git a/src/win32/posix.h b/src/win32/posix.h
new file mode 100644
index 000000000..90571ae1d
--- /dev/null
+++ b/src/win32/posix.h
@@ -0,0 +1,26 @@
+#ifndef INCLUDE_posix__w32_h__
+#define INCLUDE_posix__w32_h__
+
+#include "common.h"
+
+GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
+{
+ GIT_UNUSED_ARG(old)
+ GIT_UNUSED_ARG(new)
+ errno = ENOSYS;
+ return -1;
+}
+
+GIT_INLINE(int) p_mkdir(const char *path, int GIT_UNUSED(mode))
+{
+ GIT_UNUSED_ARG(mode)
+ return mkdir(path);
+}
+
+extern int p_unlink(const char *path);
+extern int p_lstat(const char *file_name, struct stat *buf);
+extern int p_readlink(const char *link, char *target, size_t target_len);
+extern int p_hide_directory__w32(const char *path);
+extern char *p_realpath(const char *orig_path, char *buffer);
+
+#endif
diff --git a/tests/resources/config/config10 b/tests/resources/config/config10
new file mode 100644
index 000000000..dde17911b
--- /dev/null
+++ b/tests/resources/config/config10
@@ -0,0 +1 @@
+[empty]
diff --git a/tests/resources/config/config9 b/tests/resources/config/config9
index 4359c7826..34fdc07a5 100644
--- a/tests/resources/config/config9
+++ b/tests/resources/config/config9
@@ -1,2 +1,3 @@
[core]
+ dummy2 = 42
dummy = 1
diff --git a/tests/t00-core.c b/tests/t00-core.c
index aa0008576..ba5188a43 100644
--- a/tests/t00-core.c
+++ b/tests/t00-core.c
@@ -78,9 +78,9 @@ BEGIN_TEST(path0, "get the dirname of a path")
char dir[64], *dir2;
#define DIRNAME_TEST(A, B) { \
- must_be_true(git__dirname_r(dir, sizeof(dir), A) >= 0); \
+ must_be_true(git_path_dirname_r(dir, sizeof(dir), A) >= 0); \
must_be_true(strcmp(dir, B) == 0); \
- must_be_true((dir2 = git__dirname(A)) != NULL); \
+ must_be_true((dir2 = git_path_dirname(A)) != NULL); \
must_be_true(strcmp(dir2, B) == 0); \
free(dir2); \
}
@@ -107,9 +107,9 @@ BEGIN_TEST(path1, "get the base name of a path")
char base[64], *base2;
#define BASENAME_TEST(A, B) { \
- must_be_true(git__basename_r(base, sizeof(base), A) >= 0); \
+ must_be_true(git_path_basename_r(base, sizeof(base), A) >= 0); \
must_be_true(strcmp(base, B) == 0); \
- must_be_true((base2 = git__basename(A)) != NULL); \
+ must_be_true((base2 = git_path_basename(A)) != NULL); \
must_be_true(strcmp(base2, B) == 0); \
free(base2); \
}
@@ -132,7 +132,7 @@ BEGIN_TEST(path2, "get the latest component in a path")
const char *dir;
#define TOPDIR_TEST(A, B) { \
- must_be_true((dir = git__topdir(A)) != NULL); \
+ must_be_true((dir = git_path_topdir(A)) != NULL); \
must_be_true(strcmp(dir, B) == 0); \
}
@@ -144,218 +144,18 @@ BEGIN_TEST(path2, "get the latest component in a path")
TOPDIR_TEST("/", "/");
TOPDIR_TEST("a/", "a/");
- must_be_true(git__topdir("/usr/.git") == NULL);
- must_be_true(git__topdir(".") == NULL);
- must_be_true(git__topdir("") == NULL);
- must_be_true(git__topdir("a") == NULL);
+ must_be_true(git_path_topdir("/usr/.git") == NULL);
+ must_be_true(git_path_topdir(".") == NULL);
+ must_be_true(git_path_topdir("") == NULL);
+ must_be_true(git_path_topdir("a") == NULL);
#undef TOPDIR_TEST
END_TEST
-typedef int (normalize_path)(char *, size_t, const char *, const char *);
-
-/* Assert flags */
-#define CWD_AS_PREFIX 1
-#define PATH_AS_SUFFIX 2
-#define ROOTED_PATH 4
-
-static int ensure_normalized(const char *input_path, const char *expected_path, normalize_path normalizer, int assert_flags)
-{
- int error = GIT_SUCCESS;
- char buffer_out[GIT_PATH_MAX];
- char current_workdir[GIT_PATH_MAX];
-
- error = gitfo_getcwd(current_workdir, sizeof(current_workdir));
- if (error < GIT_SUCCESS)
- return error;
-
- error = normalizer(buffer_out, sizeof(buffer_out), input_path, NULL);
- if (error < GIT_SUCCESS)
- return error;
-
- if (expected_path == NULL)
- return error;
-
- if ((assert_flags & PATH_AS_SUFFIX) != 0)
- if (git__suffixcmp(buffer_out, expected_path))
- return GIT_ERROR;
-
- if ((assert_flags & CWD_AS_PREFIX) != 0)
- if (git__prefixcmp(buffer_out, current_workdir))
- return GIT_ERROR;
-
- if ((assert_flags & ROOTED_PATH) != 0) {
- error = strcmp(expected_path, buffer_out);
- }
-
- return error;
-}
-
-static int ensure_dir_path_normalized(const char *input_path, const char *expected_path, int assert_flags)
-{
- return ensure_normalized(input_path, expected_path, gitfo_prettify_dir_path, assert_flags);
-}
-
-static int ensure_file_path_normalized(const char *input_path, const char *expected_path, int assert_flags)
-{
- return ensure_normalized(input_path, expected_path, gitfo_prettify_file_path, assert_flags);
-}
-
-BEGIN_TEST(path3, "prettify and validate a path to a file")
- must_pass(ensure_file_path_normalized("a", "a", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_file_path_normalized("./testrepo.git", "testrepo.git", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_file_path_normalized("./.git", ".git", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_file_path_normalized("./git.", "git.", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_fail(ensure_file_path_normalized("git./", NULL, 0));
- must_fail(ensure_file_path_normalized("", NULL, 0));
- must_fail(ensure_file_path_normalized(".", NULL, 0));
- must_fail(ensure_file_path_normalized("./", NULL, 0));
- must_fail(ensure_file_path_normalized("./.", NULL, 0));
- must_fail(ensure_file_path_normalized("./..", NULL, 0));
- must_fail(ensure_file_path_normalized("../.", NULL, 0));
- must_fail(ensure_file_path_normalized("./.././/", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/..", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/sub/../..", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/sub/..///..", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/sub///../..", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/sub///..///..", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/sub/../../..", NULL, 0));
- must_pass(ensure_file_path_normalized("dir", "dir", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_fail(ensure_file_path_normalized("dir//", NULL, 0));
- must_pass(ensure_file_path_normalized("./dir", "dir", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_fail(ensure_file_path_normalized("dir/.", NULL, 0));
- must_fail(ensure_file_path_normalized("dir///./", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/sub/..", NULL, 0));
- must_fail(ensure_file_path_normalized("dir//sub/..",NULL, 0));
- must_fail(ensure_file_path_normalized("dir//sub/../", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/sub/../", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/sub/../.", NULL, 0));
- must_fail(ensure_file_path_normalized("dir/s1/../s2/", NULL, 0));
- must_fail(ensure_file_path_normalized("d1/s1///s2/..//../s3/", NULL, 0));
- must_pass(ensure_file_path_normalized("d1/s1//../s2/../../d2", "d2", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_fail(ensure_file_path_normalized("dir/sub/../", NULL, 0));
- must_pass(ensure_file_path_normalized("../a/../b/c/d/../../e", "b/e", PATH_AS_SUFFIX));
- must_fail(ensure_file_path_normalized("....", NULL, 0));
- must_fail(ensure_file_path_normalized("...", NULL, 0));
- must_fail(ensure_file_path_normalized("./...", NULL, 0));
- must_fail(ensure_file_path_normalized("d1/...", NULL, 0));
- must_fail(ensure_file_path_normalized("d1/.../", NULL, 0));
- must_fail(ensure_file_path_normalized("d1/.../d2", NULL, 0));
-
- must_pass(ensure_file_path_normalized("/a", "/a", ROOTED_PATH));
- must_pass(ensure_file_path_normalized("/./testrepo.git", "/testrepo.git", ROOTED_PATH));
- must_pass(ensure_file_path_normalized("/./.git", "/.git", ROOTED_PATH));
- must_pass(ensure_file_path_normalized("/./git.", "/git.", ROOTED_PATH));
- must_fail(ensure_file_path_normalized("/git./", NULL, 0));
- must_fail(ensure_file_path_normalized("/", NULL, 0));
- must_fail(ensure_file_path_normalized("/.", NULL, 0));
- must_fail(ensure_file_path_normalized("/./", NULL, 0));
- must_fail(ensure_file_path_normalized("/./.", NULL, 0));
- must_fail(ensure_file_path_normalized("/./..", NULL, 0));
- must_fail(ensure_file_path_normalized("/../.", NULL, 0));
- must_fail(ensure_file_path_normalized("/./.././/", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/..", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/sub/../..", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/sub/..///..", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/sub///../..", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/sub///..///..", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/sub/../../..", NULL, 0));
- must_pass(ensure_file_path_normalized("/dir", "/dir", 0));
- must_fail(ensure_file_path_normalized("/dir//", NULL, 0));
- must_pass(ensure_file_path_normalized("/./dir", "/dir", 0));
- must_fail(ensure_file_path_normalized("/dir/.", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir///./", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/sub/..", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir//sub/..",NULL, 0));
- must_fail(ensure_file_path_normalized("/dir//sub/../", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/sub/../", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/sub/../.", NULL, 0));
- must_fail(ensure_file_path_normalized("/dir/s1/../s2/", NULL, 0));
- must_fail(ensure_file_path_normalized("/d1/s1///s2/..//../s3/", NULL, 0));
- must_pass(ensure_file_path_normalized("/d1/s1//../s2/../../d2", "/d2", 0));
- must_fail(ensure_file_path_normalized("/dir/sub/../", NULL, 0));
- must_fail(ensure_file_path_normalized("/....", NULL, 0));
- must_fail(ensure_file_path_normalized("/...", NULL, 0));
- must_fail(ensure_file_path_normalized("/./...", NULL, 0));
- must_fail(ensure_file_path_normalized("/d1/...", NULL, 0));
- must_fail(ensure_file_path_normalized("/d1/.../", NULL, 0));
- must_fail(ensure_file_path_normalized("/d1/.../d2", NULL, 0));
-END_TEST
-
-BEGIN_TEST(path4, "validate and prettify a path to a folder")
- must_pass(ensure_dir_path_normalized("./testrepo.git", "testrepo.git/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("./.git", ".git/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("./git.", "git./", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("git./", "git./", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized(".", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("./", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("./.", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/..", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/sub/../..", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/sub/..///..", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/sub///../..", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/sub///..///..", "", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir//", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("./dir", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/.", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir///./", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/sub/..", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir//sub/..", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir//sub/../", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/sub/../", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/sub/../.", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/s1/../s2/", "dir/s2/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("d1/s1///s2/..//../s3/", "d1/s3/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("d1/s1//../s2/../../d2", "d2/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("dir/sub/../", "dir/", CWD_AS_PREFIX | PATH_AS_SUFFIX));
- must_pass(ensure_dir_path_normalized("../a/../b/c/d/../../e", "b/e/", PATH_AS_SUFFIX));
- must_fail(ensure_dir_path_normalized("....", NULL, 0));
- must_fail(ensure_dir_path_normalized("...", NULL, 0));
- must_fail(ensure_dir_path_normalized("./...", NULL, 0));
- must_fail(ensure_dir_path_normalized("d1/...", NULL, 0));
- must_fail(ensure_dir_path_normalized("d1/.../", NULL, 0));
- must_fail(ensure_dir_path_normalized("d1/.../d2", NULL, 0));
-
- must_pass(ensure_dir_path_normalized("/./testrepo.git", "/testrepo.git/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/./.git", "/.git/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/./git.", "/git./", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/git./", "/git./", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/", "/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("//", "/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("///", "/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/.", "/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/./", "/", ROOTED_PATH));
- must_fail(ensure_dir_path_normalized("/./..", NULL, 0));
- must_fail(ensure_dir_path_normalized("/../.", NULL, 0));
- must_fail(ensure_dir_path_normalized("/./.././/", NULL, 0));
- must_pass(ensure_dir_path_normalized("/dir/..", "/", 0));
- must_pass(ensure_dir_path_normalized("/dir/sub/../..", "/", 0));
- must_fail(ensure_dir_path_normalized("/dir/sub/../../..", NULL, 0));
- must_pass(ensure_dir_path_normalized("/dir", "/dir/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/dir//", "/dir/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/./dir", "/dir/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/dir/.", "/dir/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/dir///./", "/dir/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/dir//sub/..", "/dir/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/dir/sub/../", "/dir/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("//dir/sub/../.", "/dir/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/dir/s1/../s2/", "/dir/s2/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/d1/s1///s2/..//../s3/", "/d1/s3/", ROOTED_PATH));
- must_pass(ensure_dir_path_normalized("/d1/s1//../s2/../../d2", "/d2/", ROOTED_PATH));
- must_fail(ensure_dir_path_normalized("/....", NULL, 0));
- must_fail(ensure_dir_path_normalized("/...", NULL, 0));
- must_fail(ensure_dir_path_normalized("/./...", NULL, 0));
- must_fail(ensure_dir_path_normalized("/d1/...", NULL, 0));
- must_fail(ensure_dir_path_normalized("/d1/.../", NULL, 0));
- must_fail(ensure_dir_path_normalized("/d1/.../d2", NULL, 0));
-END_TEST
-
static int ensure_joinpath(const char *path_a, const char *path_b, const char *expected_path)
{
char joined_path[GIT_PATH_MAX];
- git__joinpath(joined_path, path_a, path_b);
+ git_path_join(joined_path, path_a, path_b);
return strcmp(joined_path, expected_path) == 0 ? GIT_SUCCESS : GIT_ERROR;
}
@@ -377,7 +177,7 @@ END_TEST
static int ensure_joinpath_n(const char *path_a, const char *path_b, const char *path_c, const char *path_d, const char *expected_path)
{
char joined_path[GIT_PATH_MAX];
- git__joinpath_n(joined_path, 4, path_a, path_b, path_c, path_d);
+ git_path_join_n(joined_path, 4, path_a, path_b, path_c, path_d);
return strcmp(joined_path, expected_path) == 0 ? GIT_SUCCESS : GIT_ERROR;
}
@@ -390,37 +190,6 @@ BEGIN_TEST(path6, "properly join path components for more than one path")
must_pass(ensure_joinpath_n("a", "b", "", "/c/d", "a/b/c/d"));
END_TEST
-static int count_number_of_path_segments(const char *path)
-{
- int number = 0;
- char *current = (char *)path;
-
- while (*current)
- {
- if (*current++ == '/')
- number++;
- }
-
- assert (number > 0);
-
- return --number;
-}
-
-BEGIN_TEST(path7, "prevent a path which escapes the root directory from being prettified")
- char current_workdir[GIT_PATH_MAX];
- char prettified[GIT_PATH_MAX];
- int i = 0, number_to_escape;
-
- must_pass(gitfo_getcwd(current_workdir, sizeof(current_workdir)));
-
- number_to_escape = count_number_of_path_segments(current_workdir);
-
- for (i = 0; i < number_to_escape + 1; i++)
- git__joinpath(current_workdir, current_workdir, "../");
-
- must_fail(gitfo_prettify_dir_path(prettified, sizeof(prettified), current_workdir, NULL));
-END_TEST
-
typedef struct name_data {
int count; /* return count */
char *name; /* filename */
@@ -451,24 +220,24 @@ static int setup(walk_data *d)
{
name_data *n;
- if (gitfo_mkdir(top_dir, 0755) < 0)
+ if (p_mkdir(top_dir, 0755) < 0)
return error("can't mkdir(\"%s\")", top_dir);
- if (gitfo_chdir(top_dir) < 0)
+ if (p_chdir(top_dir) < 0)
return error("can't chdir(\"%s\")", top_dir);
if (strcmp(d->sub, ".") != 0)
- if (gitfo_mkdir(d->sub, 0755) < 0)
+ if (p_mkdir(d->sub, 0755) < 0)
return error("can't mkdir(\"%s\")", d->sub);
strcpy(path_buffer, d->sub);
state_loc = d;
for (n = d->names; n->name; n++) {
- git_file fd = gitfo_creat(n->name, 0600);
+ git_file fd = p_creat(n->name, 0600);
if (fd < 0)
return GIT_ERROR;
- gitfo_close(fd);
+ p_close(fd);
n->count = 0;
}
@@ -480,18 +249,18 @@ static int knockdown(walk_data *d)
name_data *n;
for (n = d->names; n->name; n++) {
- if (gitfo_unlink(n->name) < 0)
+ if (p_unlink(n->name) < 0)
return error("can't unlink(\"%s\")", n->name);
}
if (strcmp(d->sub, ".") != 0)
- if (gitfo_rmdir(d->sub) < 0)
+ if (p_rmdir(d->sub) < 0)
return error("can't rmdir(\"%s\")", d->sub);
- if (gitfo_chdir("..") < 0)
+ if (p_chdir("..") < 0)
return error("can't chdir(\"..\")");
- if (gitfo_rmdir(top_dir) < 0)
+ if (p_rmdir(top_dir) < 0)
return error("can't rmdir(\"%s\")", top_dir);
return 0;
@@ -546,7 +315,7 @@ BEGIN_TEST(dirent0, "make sure that the '.' folder is not traversed")
must_pass(setup(&dot));
- must_pass(gitfo_dirent(path_buffer,
+ must_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&dot));
@@ -571,7 +340,7 @@ BEGIN_TEST(dirent1, "traverse a subfolder")
must_pass(setup(&sub));
- must_pass(gitfo_dirent(path_buffer,
+ must_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&sub));
@@ -590,7 +359,7 @@ BEGIN_TEST(dirent2, "traverse a slash-terminated subfolder")
must_pass(setup(&sub_slash));
- must_pass(gitfo_dirent(path_buffer,
+ must_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&sub_slash));
@@ -619,7 +388,7 @@ BEGIN_TEST(dirent3, "make sure that empty folders are not traversed")
must_pass(setup(&empty));
- must_pass(gitfo_dirent(path_buffer,
+ must_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&empty));
@@ -627,7 +396,7 @@ BEGIN_TEST(dirent3, "make sure that empty folders are not traversed")
must_pass(check_counts(&empty));
/* make sure callback not called */
- must_pass(gitfo_dirent(path_buffer,
+ must_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
dont_call_me,
&empty));
@@ -652,7 +421,7 @@ BEGIN_TEST(dirent4, "make sure that strange looking filenames ('..c') are traver
must_pass(setup(&odd));
- must_pass(gitfo_dirent(path_buffer,
+ must_pass(git_futils_direach(path_buffer,
sizeof(path_buffer),
one_entry,
&odd));
@@ -667,12 +436,12 @@ BEGIN_TEST(filebuf0, "make sure git_filebuf_open doesn't delete an existing lock
int fd;
char test[] = "test", testlock[] = "test.lock";
- fd = gitfo_creat(testlock, 0744);
+ fd = p_creat(testlock, 0744);
must_pass(fd);
- must_pass(gitfo_close(fd));
+ must_pass(p_close(fd));
must_fail(git_filebuf_open(&file, test, 0));
- must_pass(gitfo_exists(testlock));
- must_pass(gitfo_unlink(testlock));
+ must_pass(git_futils_exists(testlock));
+ must_pass(p_unlink(testlock));
END_TEST
BEGIN_TEST(filebuf1, "make sure GIT_FILEBUF_APPEND works as expected")
@@ -680,16 +449,29 @@ BEGIN_TEST(filebuf1, "make sure GIT_FILEBUF_APPEND works as expected")
int fd;
char test[] = "test";
- fd = gitfo_creat(test, 0644);
+ fd = p_creat(test, 0644);
must_pass(fd);
- must_pass(gitfo_write(fd, "libgit2 rocks\n", 14));
- must_pass(gitfo_close(fd));
+ must_pass(p_write(fd, "libgit2 rocks\n", 14));
+ must_pass(p_close(fd));
must_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND));
must_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
must_pass(git_filebuf_commit(&file));
- must_pass(gitfo_unlink(test));
+ must_pass(p_unlink(test));
+END_TEST
+
+BEGIN_TEST(filebuf2, "make sure git_filebuf_write writes large buffer correctly")
+ git_filebuf file;
+ char test[] = "test";
+ unsigned char buf[4096 * 4]; /* 2 * WRITE_BUFFER_SIZE */
+
+ memset(buf, 0xfe, sizeof(buf));
+ must_pass(git_filebuf_open(&file, test, 0));
+ must_pass(git_filebuf_write(&file, buf, sizeof(buf)));
+ must_pass(git_filebuf_commit(&file));
+
+ must_pass(p_unlink(test));
END_TEST
BEGIN_SUITE(core)
@@ -702,11 +484,8 @@ BEGIN_SUITE(core)
ADD_TEST(path0);
ADD_TEST(path1);
ADD_TEST(path2);
- ADD_TEST(path3);
- ADD_TEST(path4);
ADD_TEST(path5);
ADD_TEST(path6);
- ADD_TEST(path7);
ADD_TEST(dirent0);
ADD_TEST(dirent1);
@@ -716,4 +495,5 @@ BEGIN_SUITE(core)
ADD_TEST(filebuf0);
ADD_TEST(filebuf1);
+ ADD_TEST(filebuf2);
END_SUITE
diff --git a/tests/t02-objread.c b/tests/t02-objread.c
index 8f11e9e33..4bcff2742 100644
--- a/tests/t02-objread.c
+++ b/tests/t02-objread.c
@@ -210,7 +210,7 @@ BEGIN_TEST(readheader0, "read only the header of several packed objects")
git_odb_object_close(obj);
}
- git_odb_close(db);
+ git_odb_close(db);
END_TEST
BEGIN_TEST(readheader1, "read only the header of several loose objects")
diff --git a/tests/t03-objwrite.c b/tests/t03-objwrite.c
index 08ddc0fd1..31f611a5c 100644
--- a/tests/t03-objwrite.c
+++ b/tests/t03-objwrite.c
@@ -31,7 +31,7 @@ static char *odb_dir = "test-objects";
static int make_odb_dir(void)
{
- if (gitfo_mkdir(odb_dir, 0755) < 0) {
+ if (p_mkdir(odb_dir, 0755) < 0) {
int err = errno;
fprintf(stderr, "can't make directory \"%s\"", odb_dir);
if (err == EEXIST)
@@ -44,9 +44,9 @@ static int make_odb_dir(void)
static int check_object_files(object_data *d)
{
- if (gitfo_exists(d->dir) < 0)
+ if (git_futils_exists(d->dir) < 0)
return -1;
- if (gitfo_exists(d->file) < 0)
+ if (git_futils_exists(d->file) < 0)
return -1;
return 0;
}
@@ -64,16 +64,16 @@ static int cmp_objects(git_rawobj *o1, git_rawobj *o2)
static int remove_object_files(object_data *d)
{
- if (gitfo_unlink(d->file) < 0) {
+ if (p_unlink(d->file) < 0) {
fprintf(stderr, "can't delete object file \"%s\"\n", d->file);
return -1;
}
- if ((gitfo_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) {
+ if ((p_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) {
fprintf(stderr, "can't remove directory \"%s\"\n", d->dir);
return -1;
}
- if (gitfo_rmdir(odb_dir) < 0) {
+ if (p_rmdir(odb_dir) < 0) {
fprintf(stderr, "can't remove directory \"%s\"\n", odb_dir);
return -1;
}
diff --git a/tests/t04-commit.c b/tests/t04-commit.c
index 0ae0cdfb2..0f480e552 100644
--- a/tests/t04-commit.c
+++ b/tests/t04-commit.c
@@ -241,12 +241,179 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
123456,
-60);
- TEST_SIGNATURE_FAIL(
+ /* Parse a signature without an author field */
+ TEST_SIGNATURE_PASS(
+ "committer <tanoku@gmail.com> 123456 -0100 \n",
+ "committer ",
+ "",
+ "tanoku@gmail.com",
+ 123456,
+ -60);
+
+ /* Parse a signature without an author field */
+ TEST_SIGNATURE_PASS(
+ "committer <tanoku@gmail.com> 123456 -0100 \n",
+ "committer ",
+ "",
+ "tanoku@gmail.com",
+ 123456,
+ -60);
+
+ /* Parse a signature with an empty author field */
+ TEST_SIGNATURE_PASS(
+ "committer <tanoku@gmail.com> 123456 -0100 \n",
+ "committer ",
+ "",
+ "tanoku@gmail.com",
+ 123456,
+ -60);
+
+ /* Parse a signature with an empty email field */
+ TEST_SIGNATURE_PASS(
+ "committer Vicent Marti <> 123456 -0100 \n",
+ "committer ",
+ "Vicent Marti",
+ "",
+ 123456,
+ -60);
+
+ /* Parse a signature with an empty email field */
+ TEST_SIGNATURE_PASS(
+ "committer Vicent Marti < > 123456 -0100 \n",
+ "committer ",
+ "Vicent Marti",
+ "",
+ 123456,
+ -60);
+
+ /* Parse a signature with empty name and email */
+ TEST_SIGNATURE_PASS(
+ "committer <> 123456 -0100 \n",
+ "committer ",
+ "",
+ "",
+ 123456,
+ -60);
+
+ /* Parse a signature with empty name and email */
+ TEST_SIGNATURE_PASS(
+ "committer <> 123456 -0100 \n",
+ "committer ",
+ "",
+ "",
+ 123456,
+ -60);
+
+ /* Parse a signature with empty name and email */
+ TEST_SIGNATURE_PASS(
+ "committer < > 123456 -0100 \n",
+ "committer ",
+ "",
+ "",
+ 123456,
+ -60);
+
+ /* Parse an obviously invalid signature */
+ TEST_SIGNATURE_PASS(
+ "committer foo<@bar> 123456 -0100 \n",
+ "committer ",
+ "foo",
+ "@bar",
+ 123456,
+ -60);
+
+ /* Parse an obviously invalid signature */
+ TEST_SIGNATURE_PASS(
+ "committer foo<@bar>123456 -0100 \n",
+ "committer ",
+ "foo",
+ "@bar",
+ 123456,
+ -60);
+
+ /* Parse an obviously invalid signature */
+ TEST_SIGNATURE_PASS(
+ "committer <>\n",
+ "committer ",
+ "",
+ "",
+ 0,
+ 0);
+
+ TEST_SIGNATURE_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 -1500 \n",
- "committer ");
+ "committer ",
+ "Vicent Marti",
+ "tanoku@gmail.com",
+ 0,
+ 0);
- TEST_SIGNATURE_FAIL(
+ TEST_SIGNATURE_PASS(
"committer Vicent Marti <tanoku@gmail.com> 123456 +0163 \n",
+ "committer ",
+ "Vicent Marti",
+ "tanoku@gmail.com",
+ 0,
+ 0);
+
+ TEST_SIGNATURE_PASS(
+ "author Vicent Marti <tanoku@gmail.com> notime \n",
+ "author ",
+ "Vicent Marti",
+ "tanoku@gmail.com",
+ 0,
+ 0);
+
+ TEST_SIGNATURE_PASS(
+ "author Vicent Marti <tanoku@gmail.com> 123456 notimezone \n",
+ "author ",
+ "Vicent Marti",
+ "tanoku@gmail.com",
+ 0,
+ 0);
+
+ TEST_SIGNATURE_PASS(
+ "author Vicent Marti <tanoku@gmail.com> notime +0100\n",
+ "author ",
+ "Vicent Marti",
+ "tanoku@gmail.com",
+ 0,
+ 0);
+
+ TEST_SIGNATURE_PASS(
+ "author Vicent Marti <tanoku@gmail.com>\n",
+ "author ",
+ "Vicent Marti",
+ "tanoku@gmail.com",
+ 0,
+ 0);
+
+ TEST_SIGNATURE_PASS(
+ "author A U Thor <author@example.com>, C O. Miter <comiter@example.com> 1234567890 -0700\n",
+ "author ",
+ "A U Thor",
+ "author@example.com",
+ 1234567890,
+ -420);
+
+ TEST_SIGNATURE_PASS(
+ "author A U Thor <author@example.com> and others 1234567890 -0700\n",
+ "author ",
+ "A U Thor",
+ "author@example.com",
+ 1234567890,
+ -420);
+
+ TEST_SIGNATURE_PASS(
+ "author A U Thor <author@example.com> and others 1234567890\n",
+ "author ",
+ "A U Thor",
+ "author@example.com",
+ 1234567890,
+ 0);
+
+ TEST_SIGNATURE_FAIL(
+ "committer Vicent Marti tanoku@gmail.com> 123456 -0100 \n",
"committer ");
TEST_SIGNATURE_FAIL(
@@ -266,12 +433,8 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
"author ");
TEST_SIGNATURE_FAIL(
- "author Vicent Marti <tanoku@gmail.com> notime \n",
- "author ");
-
- TEST_SIGNATURE_FAIL(
- "author Vicent Marti <tanoku@gmail.com>\n",
- "author ");
+ "committer Vicent Marti ><\n",
+ "committer ");
TEST_SIGNATURE_FAIL(
"author ",
@@ -282,6 +445,39 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
END_TEST
+static int try_build_signature(const char *name, const char *email, git_time_t time, int offset)
+{
+ git_signature *sign;
+ int error = GIT_SUCCESS;
+
+ sign = git_signature_new(name, email, time, offset);
+
+ if (sign == NULL)
+ error = GIT_ERROR;
+
+ git_signature_free((git_signature *)sign);
+
+ return error;
+}
+
+BEGIN_TEST(signature0, "creating a signature trims leading and trailing spaces")
+ git_signature *sign;
+ sign = git_signature_new(" nulltoken ", " emeric.fermas@gmail.com ", 1234567890, 60);
+ must_be_true(sign != NULL);
+ must_pass(strcmp(sign->name, "nulltoken"));
+ must_pass(strcmp(sign->email, "emeric.fermas@gmail.com"));
+ git_signature_free((git_signature *)sign);
+END_TEST
+
+BEGIN_TEST(signature1, "can not create a signature with empty name or email")
+ must_pass(try_build_signature("nulltoken", "emeric.fermas@gmail.com", 1234567890, 60));
+
+ must_fail(try_build_signature("", "emeric.fermas@gmail.com", 1234567890, 60));
+ must_fail(try_build_signature(" ", "emeric.fermas@gmail.com", 1234567890, 60));
+ must_fail(try_build_signature("nulltoken", "", 1234567890, 60));
+ must_fail(try_build_signature("nulltoken", " ", 1234567890, 60));
+END_TEST
+
/* External declaration for testing the buffer parsing method */
int commit_parse_buffer(git_commit *commit, void *data, size_t len, unsigned int parse_flags);
@@ -359,7 +555,7 @@ BEGIN_TEST(details0, "query the details on a parsed commit")
git_repository *repo;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
-
+
for (i = 0; i < commit_count; ++i) {
git_oid id;
git_commit *commit;
@@ -415,19 +611,21 @@ This is a commit created in memory and it will be written back to disk\n"
static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
-
BEGIN_TEST(write0, "write a new commit object from memory to disk")
git_repository *repo;
git_commit *commit;
git_oid tree_id, parent_id, commit_id;
const git_signature *author, *committer;
- /* char hex_oid[41]; */
+ git_commit *parent;
+ git_tree *tree;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
-
git_oid_fromstr(&tree_id, tree_oid);
+ must_pass(git_tree_lookup(&tree, repo, &tree_id));
+
git_oid_fromstr(&parent_id, commit_ids[4]);
+ must_pass(git_commit_lookup(&parent, repo, &parent_id));
/* create signatures */
committer = git_signature_new(COMMITTER_NAME, COMMITTER_EMAIL, 123456789, 60);
@@ -443,8 +641,11 @@ BEGIN_TEST(write0, "write a new commit object from memory to disk")
author,
committer,
COMMIT_MESSAGE,
- &tree_id,
- 1, &parent_id));
+ tree,
+ 1, parent));
+
+ git_object_close((git_object *)parent);
+ git_object_close((git_object *)tree);
git_signature_free((git_signature *)committer);
git_signature_free((git_signature *)author);
@@ -486,10 +687,12 @@ BEGIN_TEST(root0, "create a root commit")
const char *branch_name = "refs/heads/root-commit-branch";
git_reference *head, *branch;
char *head_old;
+ git_tree *tree;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&tree_id, tree_oid);
+ must_pass(git_tree_lookup(&tree, repo, &tree_id));
/* create signatures */
committer = git_signature_new(COMMITTER_NAME, COMMITTER_EMAIL, 123456789, 60);
@@ -513,9 +716,10 @@ BEGIN_TEST(root0, "create a root commit")
author,
committer,
ROOT_COMMIT_MESSAGE,
- &tree_id,
+ tree,
0));
+ git_object_close((git_object *)tree);
git_signature_free((git_signature *)committer);
git_signature_free((git_signature *)author);
@@ -548,7 +752,9 @@ BEGIN_SUITE(commit)
ADD_TEST(details0);
ADD_TEST(write0);
- //ADD_TEST(write1);
ADD_TEST(root0);
+
+ ADD_TEST(signature0);
+ ADD_TEST(signature1);
END_SUITE
diff --git a/tests/t05-revwalk.c b/tests/t05-revwalk.c
index ac5de2167..ab509ab94 100644
--- a/tests/t05-revwalk.c
+++ b/tests/t05-revwalk.c
@@ -74,7 +74,7 @@ static int get_commit_index(git_oid *raw_oid)
char oid[40];
git_oid_fmt(oid, raw_oid);
-
+
for (i = 0; i < commit_count; ++i)
if (memcmp(oid, commit_ids[i], 40) == 0)
return i;
@@ -108,7 +108,7 @@ static int test_walk(git_revwalk *walk, const git_oid *root,
}*/
}
- for (i = 0; i < results_count; ++i)
+ for (i = 0; i < results_count; ++i)
if (memcmp(possible_results[i],
result_array, result_bytes) == 0)
return GIT_SUCCESS;
diff --git a/tests/t06-index.c b/tests/t06-index.c
index 27819c02a..3cbb5a9f0 100644
--- a/tests/t06-index.c
+++ b/tests/t06-index.c
@@ -145,8 +145,8 @@ BEGIN_TEST(write0, "write an index back to disk")
must_pass(cmp_files(TEST_INDEXBIG_PATH, "index_rewrite"));
git_index_free(index);
-
- gitfo_unlink("index_rewrite");
+
+ p_unlink("index_rewrite");
END_TEST
BEGIN_TEST(sort0, "sort the entires in an index")
@@ -187,7 +187,7 @@ BEGIN_TEST(add0, "add a new file to the index")
must_pass(git_index_entrycount(index) == 0);
/* Create a new file in the working directory */
- must_pass(gitfo_mkdir_2file(TEMP_REPO_FOLDER "myrepo/test.txt"));
+ must_pass(git_futils_mkpath2file(TEMP_REPO_FOLDER "myrepo/test.txt"));
must_pass(git_filebuf_open(&file, TEMP_REPO_FOLDER "myrepo/test.txt", 0));
must_pass(git_filebuf_write(&file, "hey there\n", 10));
must_pass(git_filebuf_commit(&file));
diff --git a/tests/t08-tag.c b/tests/t08-tag.c
index 48d48fe39..64a939f0e 100644
--- a/tests/t08-tag.c
+++ b/tests/t08-tag.c
@@ -88,10 +88,12 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
git_oid target_id, tag_id;
const git_signature *tagger;
git_reference *ref_tag;
+ git_object *target;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&target_id, tagged_commit);
+ must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT));
/* create signature */
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
@@ -101,11 +103,12 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
&tag_id, /* out id */
repo,
"the-tag",
- &target_id,
- GIT_OBJ_COMMIT,
+ target,
tagger,
- TAGGER_MESSAGE));
+ TAGGER_MESSAGE,
+ 0));
+ git_object_close(target);
git_signature_free((git_signature *)tagger);
must_pass(git_tag_lookup(&tag, repo, &tag_id));
@@ -132,42 +135,16 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
END_TEST
-BEGIN_TEST(write1, "write a tag to the repository which points to an unknown oid should fail")
- git_repository *repo;
- git_oid target_id, tag_id;
- const git_signature *tagger;
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
-
- git_oid_fromstr(&target_id, "deadbeef1b46c854b31185ea97743be6a8774479");
-
- /* create signature */
- tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
- must_be_true(tagger != NULL);
-
- must_fail(git_tag_create(
- &tag_id, /* out id */
- repo,
- "the-zombie-tag",
- &target_id,
- GIT_OBJ_COMMIT,
- tagger,
- TAGGER_MESSAGE));
-
- git_signature_free((git_signature *)tagger);
-
- git_repository_free(repo);
-
-END_TEST
-
BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already existing tag")
git_repository *repo;
git_oid target_id, tag_id;
const git_signature *tagger;
+ git_object *target;
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&target_id, tagged_commit);
+ must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT));
/* create signature */
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
@@ -177,11 +154,12 @@ BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already
&tag_id, /* out id */
repo,
"e90810b",
- &target_id,
- GIT_OBJ_COMMIT,
+ target,
tagger,
- TAGGER_MESSAGE));
+ TAGGER_MESSAGE,
+ 0));
+ git_object_close(target);
git_signature_free((git_signature *)tagger);
git_repository_free(repo);
@@ -193,10 +171,12 @@ BEGIN_TEST(write3, "Replace an already existing tag")
git_oid target_id, tag_id, old_tag_id;
const git_signature *tagger;
git_reference *ref_tag;
+ git_object *target;
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
git_oid_fromstr(&target_id, tagged_commit);
+ must_pass(git_object_lookup(&target, repo, &target_id, GIT_OBJ_COMMIT));
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
git_oid_cpy(&old_tag_id, git_reference_oid(ref_tag));
@@ -205,15 +185,16 @@ BEGIN_TEST(write3, "Replace an already existing tag")
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
must_be_true(tagger != NULL);
- must_pass(git_tag_create_f(
+ must_pass(git_tag_create(
&tag_id, /* out id */
repo,
"e90810b",
- &target_id,
- GIT_OBJ_COMMIT,
+ target,
tagger,
- TAGGER_MESSAGE));
+ TAGGER_MESSAGE,
+ 1));
+ git_object_close(target);
git_signature_free((git_signature *)tagger);
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
@@ -242,7 +223,6 @@ BEGIN_SUITE(tag)
ADD_TEST(read0);
ADD_TEST(read1);
ADD_TEST(write0);
- ADD_TEST(write1);
ADD_TEST(write2);
ADD_TEST(write3);
ADD_TEST(write4);
diff --git a/tests/t10-refs.c b/tests/t10-refs.c
index 5efe80447..fb252f427 100644
--- a/tests/t10-refs.c
+++ b/tests/t10-refs.c
@@ -48,7 +48,7 @@ BEGIN_TEST(readtag0, "lookup a loose tag reference")
must_be_true(git_object_type(object) == GIT_OBJ_TAG);
/* Ensure the name of the tag matches the name of the reference */
- git__joinpath(ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object));
+ git_path_join(ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object));
must_be_true(strcmp(ref_name_from_tag_name, loose_tag_ref_name) == 0);
git_object_close(object);
@@ -209,10 +209,10 @@ BEGIN_TEST(create0, "create a new symbolic reference")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Retrieve the physical path to the symbolic ref for further cleaning */
- git__joinpath(ref_path, repo->path_repository, new_head_tracker);
+ git_path_join(ref_path, repo->path_repository, new_head_tracker);
/* Create and write the new symbolic reference */
- must_pass(git_reference_create_symbolic(&new_reference, repo, new_head_tracker, current_head_target));
+ must_pass(git_reference_create_symbolic(&new_reference, repo, new_head_tracker, current_head_target, 0));
/* Ensure the reference can be looked-up... */
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head_tracker));
@@ -251,8 +251,8 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
- git__joinpath(ref_path, repo->path_repository, new_head_tracker);
- must_pass(git_reference_create_symbolic(&new_reference, repo, new_head_tracker, current_head_target));
+ git_path_join(ref_path, repo->path_repository, new_head_tracker);
+ must_pass(git_reference_create_symbolic(&new_reference, repo, new_head_tracker, current_head_target, 0));
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head_tracker));
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
@@ -273,10 +273,10 @@ BEGIN_TEST(create2, "create a new OID reference")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Retrieve the physical path to the symbolic ref for further cleaning */
- git__joinpath(ref_path, repo->path_repository, new_head);
+ git_path_join(ref_path, repo->path_repository, new_head);
/* Create and write the new object id reference */
- must_pass(git_reference_create_oid(&new_reference, repo, new_head, &id));
+ must_pass(git_reference_create_oid(&new_reference, repo, new_head, &id, 0));
/* Ensure the reference can be looked-up... */
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head));
@@ -310,7 +310,7 @@ BEGIN_TEST(create3, "Can not create a new OID reference which targets at an unkn
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
/* Create and write the new object id reference */
- must_fail(git_reference_create_oid(&new_reference, repo, new_head, &id));
+ must_fail(git_reference_create_oid(&new_reference, repo, new_head, &id, 0));
/* Ensure the reference can't be looked-up... */
must_fail(git_reference_lookup(&looked_up_ref, repo, new_head));
@@ -329,16 +329,16 @@ BEGIN_TEST(overwrite0, "Overwrite an existing symbolic reference")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* The target needds to exist and we need to check the name has changed */
- must_pass(git_reference_create_symbolic(&branch_ref, repo, ref_branch_name, ref_master_name));
- must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_branch_name));
+ must_pass(git_reference_create_symbolic(&branch_ref, repo, ref_branch_name, ref_master_name, 0));
+ must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_branch_name, 0));
/* Ensure it points to the right place*/
must_pass(git_reference_lookup(&ref, repo, ref_name));
must_be_true(git_reference_type(ref) & GIT_REF_SYMBOLIC);
must_be_true(!strcmp(git_reference_target(ref), ref_branch_name));
/* Ensure we can't create it unless we force it to */
- must_fail(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name));
- must_pass(git_reference_create_symbolic_f(&ref, repo, ref_name, ref_master_name));
+ must_fail(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 0));
+ must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 1));
/* Ensure it points to the right place */
must_pass(git_reference_lookup(&ref, repo, ref_name));
@@ -360,15 +360,15 @@ BEGIN_TEST(overwrite1, "Overwrite an existing object id reference")
git_oid_cpy(&id, git_reference_oid(ref));
/* Create it */
- must_pass(git_reference_create_oid(&ref, repo, ref_name, &id));
+ must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
must_pass(git_reference_lookup(&ref, repo, ref_test_name));
must_be_true(ref->type & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
/* Ensure we can't overwrite unless we force it */
- must_fail(git_reference_create_oid(&ref, repo, ref_name, &id));
- must_pass(git_reference_create_oid_f(&ref, repo, ref_name, &id));
+ must_fail(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
+ must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 1));
/* Ensure it has been overwritten */
must_pass(git_reference_lookup(&ref, repo, ref_name));
@@ -388,9 +388,9 @@ BEGIN_TEST(overwrite2, "Overwrite an existing object id reference with a symboli
must_be_true(ref->type & GIT_REF_OID);
git_oid_cpy(&id, git_reference_oid(ref));
- must_pass(git_reference_create_oid(&ref, repo, ref_name, &id));
- must_fail(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name));
- must_pass(git_reference_create_symbolic_f(&ref, repo, ref_name, ref_master_name));
+ must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
+ must_fail(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 0));
+ must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 1));
/* Ensure it points to the right place */
must_pass(git_reference_lookup(&ref, repo, ref_name));
@@ -412,10 +412,10 @@ BEGIN_TEST(overwrite3, "Overwrite an existing symbolic reference with an object
git_oid_cpy(&id, git_reference_oid(ref));
/* Create the symbolic ref */
- must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name));
+ must_pass(git_reference_create_symbolic(&ref, repo, ref_name, ref_master_name, 0));
/* It shouldn't overwrite unless we tell it to */
- must_fail(git_reference_create_oid(&ref, repo, ref_name, &id));
- must_pass(git_reference_create_oid_f(&ref, repo, ref_name, &id));
+ must_fail(git_reference_create_oid(&ref, repo, ref_name, &id, 0));
+ must_pass(git_reference_create_oid(&ref, repo, ref_name, &id, 1));
/* Ensure it points to the right place */
must_pass(git_reference_lookup(&ref, repo, ref_name));
@@ -431,9 +431,9 @@ BEGIN_TEST(pack0, "create a packfile for an empty folder")
const int mode = 0755; /* or 0777 ? */
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
-
- git__joinpath_n(temp_path, 3, repo->path_repository, GIT_REFS_HEADS_DIR, "empty_dir");
- must_pass(gitfo_mkdir_recurs(temp_path, mode));
+
+ git_path_join_n(temp_path, 3, repo->path_repository, GIT_REFS_HEADS_DIR, "empty_dir");
+ must_pass(git_futils_mkdir_r(temp_path, mode));
must_pass(git_reference_packall(repo));
@@ -446,12 +446,12 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
char temp_path[GIT_PATH_MAX];
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
-
+
/* Ensure a known loose ref can be looked up */
must_pass(git_reference_lookup(&reference, repo, loose_tag_ref_name));
must_be_true((reference->type & GIT_REF_PACKED) == 0);
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
-
+
/*
* We are now trying to pack also a loose reference
* called `points_to_blob`, to make sure we can properly
@@ -460,8 +460,8 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
must_pass(git_reference_packall(repo));
/* Ensure the packed-refs file exists */
- git__joinpath(temp_path, repo->path_repository, GIT_PACKEDREFS_FILE);
- must_pass(gitfo_exists(temp_path));
+ git_path_join(temp_path, repo->path_repository, GIT_PACKEDREFS_FILE);
+ must_pass(git_futils_exists(temp_path));
/* Ensure the known ref can still be looked up but is now packed */
must_pass(git_reference_lookup(&reference, repo, loose_tag_ref_name));
@@ -469,8 +469,8 @@ BEGIN_TEST(pack1, "create a packfile from all the loose rn a repo")
must_be_true(strcmp(reference->name, loose_tag_ref_name) == 0);
/* Ensure the known ref has been removed from the loose folder structure */
- git__joinpath(temp_path, repo->path_repository, loose_tag_ref_name);
- must_pass(!gitfo_exists(temp_path));
+ git_path_join(temp_path, repo->path_repository, loose_tag_ref_name);
+ must_pass(!git_futils_exists(temp_path));
close_temp_repo(repo);
END_TEST
@@ -484,8 +484,8 @@ BEGIN_TEST(rename0, "rename a loose reference")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure the ref doesn't exist on the file system */
- git__joinpath(temp_path, repo->path_repository, new_name);
- must_pass(!gitfo_exists(temp_path));
+ git_path_join(temp_path, repo->path_repository, new_name);
+ must_pass(!git_futils_exists(temp_path));
/* Retrieval of the reference to rename */
must_pass(git_reference_lookup(&looked_up_ref, repo, loose_tag_ref_name));
@@ -494,7 +494,7 @@ BEGIN_TEST(rename0, "rename a loose reference")
must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
/* Now that the reference is renamed... */
- must_pass(git_reference_rename(looked_up_ref, new_name));
+ must_pass(git_reference_rename(looked_up_ref, new_name, 0));
must_be_true(!strcmp(looked_up_ref->name, new_name));
/* ...It can't be looked-up with the old name... */
@@ -509,8 +509,8 @@ BEGIN_TEST(rename0, "rename a loose reference")
must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
/* ...and the ref can be found in the file system */
- git__joinpath(temp_path, repo->path_repository, new_name);
- must_pass(gitfo_exists(temp_path));
+ git_path_join(temp_path, repo->path_repository, new_name);
+ must_pass(git_futils_exists(temp_path));
close_temp_repo(repo);
END_TEST
@@ -524,8 +524,8 @@ BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure the ref doesn't exist on the file system */
- git__joinpath(temp_path, repo->path_repository, packed_head_name);
- must_pass(!gitfo_exists(temp_path));
+ git_path_join(temp_path, repo->path_repository, packed_head_name);
+ must_pass(!git_futils_exists(temp_path));
/* The reference can however be looked-up... */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
@@ -534,7 +534,7 @@ BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
must_be_true((looked_up_ref->type & GIT_REF_PACKED) != 0);
/* Now that the reference is renamed... */
- must_pass(git_reference_rename(looked_up_ref, brand_new_name));
+ must_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
must_be_true(!strcmp(looked_up_ref->name, brand_new_name));
/* ...It can't be looked-up with the old name... */
@@ -549,8 +549,8 @@ BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
/* ...and the ref now happily lives in the file system */
- git__joinpath(temp_path, repo->path_repository, brand_new_name);
- must_pass(gitfo_exists(temp_path));
+ git_path_join(temp_path, repo->path_repository, brand_new_name);
+ must_pass(git_futils_exists(temp_path));
close_temp_repo(repo);
END_TEST
@@ -564,8 +564,8 @@ BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure the other reference exists on the file system */
- git__joinpath(temp_path, repo->path_repository, packed_test_head_name);
- must_pass(gitfo_exists(temp_path));
+ git_path_join(temp_path, repo->path_repository, packed_test_head_name);
+ must_pass(git_futils_exists(temp_path));
/* Lookup the other reference */
must_pass(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
@@ -580,7 +580,7 @@ BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference
must_be_true((looked_up_ref->type & GIT_REF_PACKED) != 0);
/* Now that the reference is renamed... */
- must_pass(git_reference_rename(looked_up_ref, brand_new_name));
+ must_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
/* Lookup the other reference */
must_pass(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
@@ -589,7 +589,7 @@ BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference
must_be_true((another_looked_up_ref->type & GIT_REF_PACKED) == 0);
/* Ensure the other ref still exists on the file system */
- must_pass(gitfo_exists(temp_path));
+ must_pass(git_futils_exists(temp_path));
close_temp_repo(repo);
END_TEST
@@ -604,7 +604,7 @@ BEGIN_TEST(rename3, "can not rename a reference with the name of an existing ref
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
/* Can not be renamed to the name of another existing reference. */
- must_fail(git_reference_rename(looked_up_ref, packed_test_head_name));
+ must_fail(git_reference_rename(looked_up_ref, packed_test_head_name, 0));
/* Failure to rename it hasn't corrupted its state */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
@@ -623,10 +623,10 @@ BEGIN_TEST(rename4, "can not rename a reference with an invalid name")
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
/* Can not be renamed with an invalid name. */
- must_fail(git_reference_rename(looked_up_ref, "Hello! I'm a very invalid name."));
+ must_fail(git_reference_rename(looked_up_ref, "Hello! I'm a very invalid name.", 0));
/* Can not be renamed outside of the refs hierarchy. */
- must_fail(git_reference_rename(looked_up_ref, "i-will-sudo-you"));
+ must_fail(git_reference_rename(looked_up_ref, "i-will-sudo-you", 0));
/* Failure to rename it hasn't corrupted its state */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
@@ -645,7 +645,7 @@ BEGIN_TEST(rename5, "can force-rename a reference with the name of an existing r
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
/* Can be force-renamed to the name of another existing reference. */
- must_pass(git_reference_rename_f(looked_up_ref, packed_test_head_name));
+ must_pass(git_reference_rename(looked_up_ref, packed_test_head_name, 1));
/* Check we actually renamed it */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
@@ -671,14 +671,14 @@ BEGIN_TEST(rename6, "can not overwrite name of existing reference")
git_oid_cpy(&id, git_reference_oid(ref));
/* Create loose references */
- must_pass(git_reference_create_oid(&ref_one, repo, ref_one_name, &id));
- must_pass(git_reference_create_oid(&ref_two, repo, ref_two_name, &id));
+ must_pass(git_reference_create_oid(&ref_one, repo, ref_one_name, &id, 0));
+ must_pass(git_reference_create_oid(&ref_two, repo, ref_two_name, &id, 0));
/* Pack everything */
must_pass(git_reference_packall(repo));
/* Attempt to create illegal reference */
- must_fail(git_reference_create_oid(&ref_one_new, repo, ref_one_name_new, &id));
+ must_fail(git_reference_create_oid(&ref_one_new, repo, ref_one_name_new, &id, 0));
/* Illegal reference couldn't be created so this is supposed to fail */
must_fail(git_reference_lookup(&ref_one_new, repo, ref_one_name_new));
@@ -694,8 +694,8 @@ BEGIN_TEST(delete0, "deleting a ref which is both packed and loose should remove
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
/* Ensure the loose reference exists on the file system */
- git__joinpath(temp_path, repo->path_repository, packed_test_head_name);
- must_pass(gitfo_exists(temp_path));
+ git_path_join(temp_path, repo->path_repository, packed_test_head_name);
+ must_pass(git_futils_exists(temp_path));
/* Lookup the reference */
must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
@@ -710,7 +710,7 @@ BEGIN_TEST(delete0, "deleting a ref which is both packed and loose should remove
must_fail(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
/* Ensure the loose reference doesn't exist any longer on the file system */
- must_pass(!gitfo_exists(temp_path));
+ must_pass(!git_futils_exists(temp_path));
close_temp_repo(repo);
END_TEST
@@ -913,7 +913,7 @@ BEGIN_TEST(list0, "try to list all the references in our test repo")
/* We have exactly 8 refs in total if we include the packed ones:
* there is a reference that exists both in the packfile and as
* loose, but we only list it once */
- must_be_true(ref_list.count == 8);
+ must_be_true(ref_list.count == 8);
git_strarray_free(&ref_list);
git_repository_free(repo);
@@ -925,7 +925,7 @@ BEGIN_TEST(list1, "try to list only the symbolic references")
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
must_pass(git_reference_listall(&ref_list, repo, GIT_REF_SYMBOLIC));
- must_be_true(ref_list.count == 0); /* no symrefs in the test repo */
+ must_be_true(ref_list.count == 0); /* no symrefs in the test repo */
git_strarray_free(&ref_list);
git_repository_free(repo);
diff --git a/tests/t12-repo.c b/tests/t12-repo.c
index 3447f2b22..6d897a14e 100644
--- a/tests/t12-repo.c
+++ b/tests/t12-repo.c
@@ -104,10 +104,10 @@ static int ensure_repository_init(
char path_odb[GIT_PATH_MAX];
git_repository *repo;
- if (gitfo_isdir(working_directory) == GIT_SUCCESS)
+ if (git_futils_isdir(working_directory) == GIT_SUCCESS)
return GIT_ERROR;
- git__joinpath(path_odb, expected_path_repository, GIT_OBJECTS_DIR);
+ git_path_join(path_odb, expected_path_repository, GIT_OBJECTS_DIR);
if (git_repository_init(&repo, working_directory, repository_kind) < GIT_SUCCESS)
return GIT_ERROR;
@@ -127,6 +127,11 @@ static int ensure_repository_init(
if (git__suffixcmp(repo->path_index, expected_path_index) != 0)
goto cleanup;
+#ifdef GIT_WIN32
+ if ((GetFileAttributes(repo->path_repository) & FILE_ATTRIBUTE_HIDDEN) == 0)
+ goto cleanup;
+#endif
+
if (git_repository_is_bare(repo) == 1)
goto cleanup;
} else if (git_repository_is_bare(repo) == 0)
@@ -149,8 +154,8 @@ cleanup:
BEGIN_TEST(init0, "initialize a standard repo")
char path_index[GIT_PATH_MAX], path_repository[GIT_PATH_MAX];
- git__joinpath(path_repository, TEMP_REPO_FOLDER, GIT_DIR);
- git__joinpath(path_index, path_repository, GIT_INDEX_FILE);
+ git_path_join(path_repository, TEMP_REPO_FOLDER, GIT_DIR);
+ git_path_join(path_index, path_repository, GIT_INDEX_FILE);
must_pass(ensure_repository_init(TEMP_REPO_FOLDER, STANDARD_REPOSITORY, path_index, path_repository, TEMP_REPO_FOLDER));
must_pass(ensure_repository_init(TEMP_REPO_FOLDER_NS, STANDARD_REPOSITORY, path_index, path_repository, TEMP_REPO_FOLDER));
@@ -159,7 +164,7 @@ END_TEST
BEGIN_TEST(init1, "initialize a bare repo")
char path_repository[GIT_PATH_MAX];
- git__joinpath(path_repository, TEMP_REPO_FOLDER, "");
+ git_path_join(path_repository, TEMP_REPO_FOLDER, "");
must_pass(ensure_repository_init(TEMP_REPO_FOLDER, BARE_REPOSITORY, NULL, path_repository, NULL));
must_pass(ensure_repository_init(TEMP_REPO_FOLDER_NS, BARE_REPOSITORY, NULL, path_repository, NULL));
@@ -171,10 +176,10 @@ BEGIN_TEST(init2, "Initialize and open a bare repo with a relative path escaping
const int mode = 0755; /* or 0777 ? */
git_repository* repo;
- must_pass(gitfo_getcwd(current_workdir, sizeof(current_workdir)));
+ must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
- git__joinpath(path_repository, TEMP_REPO_FOLDER, "a/b/c/");
- must_pass(gitfo_mkdir_recurs(path_repository, mode));
+ git_path_join(path_repository, TEMP_REPO_FOLDER, "a/b/c/");
+ must_pass(git_futils_mkdir_r(path_repository, mode));
must_pass(chdir(path_repository));
@@ -237,14 +242,14 @@ BEGIN_TEST(open2, "Open a bare repository with a relative path escaping out of t
git_repository* repo;
/* Setup the repository to open */
- must_pass(gitfo_getcwd(current_workdir, sizeof(current_workdir)));
+ must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
strcpy(path_repository, current_workdir);
- git__joinpath_n(path_repository, 3, path_repository, TEMP_REPO_FOLDER, "a/d/e.git");
+ git_path_join_n(path_repository, 3, path_repository, TEMP_REPO_FOLDER, "a/d/e.git");
must_pass(copydir_recurs(REPOSITORY_FOLDER, path_repository));
/* Change the current working directory */
- git__joinpath(new_current_workdir, TEMP_REPO_FOLDER, "a/b/c/");
- must_pass(gitfo_mkdir_recurs(new_current_workdir, mode));
+ git_path_join(new_current_workdir, TEMP_REPO_FOLDER, "a/b/c/");
+ must_pass(git_futils_mkdir_r(new_current_workdir, mode));
must_pass(chdir(new_current_workdir));
must_pass(git_repository_open(&repo, "../../d/e.git"));
@@ -268,6 +273,46 @@ BEGIN_TEST(empty0, "test if a repository is empty or not")
git_repository_free(repo_empty);
END_TEST
+BEGIN_TEST(detached0, "test if HEAD is detached")
+ git_repository *repo;
+ git_reference *ref;
+ git_oid oid;
+
+ must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
+
+ must_be_true(git_repository_head_detached(repo) == 0);
+
+ /* detach the HEAD */
+ git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd");
+ must_pass(git_reference_create_oid(&ref, repo, "HEAD", &oid, 1));
+ must_be_true(git_repository_head_detached(repo) == 1);
+
+ /* take the reop back to it's original state */
+ must_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/master", 1));
+ must_be_true(git_repository_head_detached(repo) == 0);
+
+ git_repository_free(repo);
+END_TEST
+
+BEGIN_TEST(orphan0, "test if HEAD is orphan")
+ git_repository *repo;
+ git_reference *ref;
+
+ must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
+
+ must_be_true(git_repository_head_orphan(repo) == 0);
+
+ /* orphan HEAD */
+ must_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/orphan", 1));
+ must_be_true(git_repository_head_orphan(repo) == 1);
+
+ /* take the reop back to it's original state */
+ must_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/master", 1));
+ must_be_true(git_repository_head_orphan(repo) == 0);
+
+ git_repository_free(repo);
+END_TEST
+
#define DISCOVER_FOLDER TEST_RESOURCES "/discover.git"
#define SUB_REPOSITORY_FOLDER_NAME "sub_repo"
@@ -305,20 +350,20 @@ static int write_file(const char *path, const char *content)
int error;
git_file file;
- if (gitfo_exists(path) == GIT_SUCCESS) {
- error = gitfo_unlink(path);
+ if (git_futils_exists(path) == GIT_SUCCESS) {
+ error = p_unlink(path);
if (error < GIT_SUCCESS)
return error;
}
- file = gitfo_creat_force(path, 0644);
+ file = git_futils_creat_withpath(path, 0644);
if (file < GIT_SUCCESS)
return file;
- error = gitfo_write(file, (void*)content, strlen(content) * sizeof(char));
+ error = p_write(file, (void*)content, strlen(content) * sizeof(char));
- gitfo_close(file);
+ p_close(file);
return error;
}
@@ -329,7 +374,7 @@ static int append_ceiling_dir(char *ceiling_dirs, const char *path)
int len = strlen(ceiling_dirs);
int error;
- error = gitfo_prettify_dir_path(ceiling_dirs + len + (len ? 1 : 0), GIT_PATH_MAX, path, NULL);
+ error = git_path_prettify_dir(ceiling_dirs + len + (len ? 1 : 0), path, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to append ceiling directory.");
@@ -349,7 +394,7 @@ BEGIN_TEST(discover0, "test discover")
rmdir_recurs(DISCOVER_FOLDER);
must_pass(append_ceiling_dir(ceiling_dirs,TEST_RESOURCES));
- gitfo_mkdir_recurs(DISCOVER_FOLDER, mode);
+ git_futils_mkdir_r(DISCOVER_FOLDER, mode);
must_be_true(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs) == GIT_ENOTAREPO);
@@ -358,15 +403,15 @@ BEGIN_TEST(discover0, "test discover")
git_repository_free(repo);
must_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0));
- must_pass(gitfo_mkdir_recurs(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode));
+ must_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode));
must_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
- must_pass(gitfo_mkdir_recurs(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode));
+ must_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, mode));
must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path));
- must_pass(gitfo_mkdir_recurs(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, mode));
+ must_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, mode));
must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT));
must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT));
must_pass(write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../"));
@@ -375,26 +420,26 @@ BEGIN_TEST(discover0, "test discover")
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path));
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path));
- must_pass(gitfo_mkdir_recurs(ALTERNATE_MALFORMED_FOLDER1, mode));
+ must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, mode));
must_pass(write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:"));
- must_pass(gitfo_mkdir_recurs(ALTERNATE_MALFORMED_FOLDER2, mode));
+ must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER2, mode));
must_pass(write_file(ALTERNATE_MALFORMED_FOLDER2 "/" DOT_GIT, "gitdir:"));
- must_pass(gitfo_mkdir_recurs(ALTERNATE_MALFORMED_FOLDER3, mode));
+ must_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER3, mode));
must_pass(write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n"));
- must_pass(gitfo_mkdir_recurs(ALTERNATE_NOT_FOUND_FOLDER, mode));
+ must_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, mode));
must_pass(write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist"));
must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs));
must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs));
must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs));
- must_be_true(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs) == GIT_ENOTAREPO);
+ must_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs));
must_pass(append_ceiling_dir(ceiling_dirs, SUB_REPOSITORY_FOLDER));
//this must pass as ceiling_directories cannot predent the current
//working directory to be checked
must_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs));
- must_be_true(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs) == GIT_ENOTAREPO);
- must_be_true(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs) == GIT_ENOTAREPO);
- must_be_true(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs) == GIT_ENOTAREPO);
+ must_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs));
+ must_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs));
+ must_fail(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs));
//.gitfile redirection should not be affected by ceiling directories
must_pass(ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path));
@@ -416,6 +461,8 @@ BEGIN_SUITE(repository)
ADD_TEST(open1);
ADD_TEST(open2);
ADD_TEST(empty0);
+ ADD_TEST(detached0);
+ ADD_TEST(orphan0);
ADD_TEST(discover0);
END_SUITE
diff --git a/tests/t15-config.c b/tests/t15-config.c
index 63fe8e100..c85d336a6 100644
--- a/tests/t15-config.c
+++ b/tests/t15-config.c
@@ -235,6 +235,68 @@ BEGIN_TEST(config11, "fall back to the global config")
git_repository_free(repo);
END_TEST
+BEGIN_TEST(config12, "delete a value")
+ git_config *cfg;
+ int i;
+
+ /* By freeing the config, we make sure we flush the values */
+ must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
+ must_pass(git_config_set_int(cfg, "core.dummy", 5));
+ git_config_free(cfg);
+
+ must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
+ must_pass(git_config_del(cfg, "core.dummy"));
+ git_config_free(cfg);
+
+ must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
+ must_be_true(git_config_get_int(cfg, "core.dummy", &i) == GIT_ENOTFOUND);
+ must_pass(git_config_set_int(cfg, "core.dummy", 1));
+ git_config_free(cfg);
+END_TEST
+
+BEGIN_TEST(config13, "can't delete a non-existent value")
+ git_config *cfg;
+
+ /* By freeing the config, we make sure we flush the values */
+ must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
+ must_be_true(git_config_del(cfg, "core.imaginary") == GIT_ENOTFOUND);
+ git_config_free(cfg);
+END_TEST
+
+BEGIN_TEST(config14, "don't fail horribly if a section header is in the last line")
+ git_config *cfg;
+
+ /* By freeing the config, we make sure we flush the values */
+ must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config10"));
+ git_config_free(cfg);
+END_TEST
+
+BEGIN_TEST(config15, "add a variable in an existing section")
+ git_config *cfg;
+ int i;
+
+ /* By freeing the config, we make sure we flush the values */
+ must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config10"));
+ must_pass(git_config_set_int(cfg, "empty.tmp", 5));
+ must_pass(git_config_get_int(cfg, "empty.tmp", &i));
+ must_be_true(i == 5);
+ must_pass(git_config_del(cfg, "empty.tmp"));
+ git_config_free(cfg);
+END_TEST
+
+BEGIN_TEST(config16, "add a variable in a new section")
+ git_config *cfg;
+ int i;
+
+ /* By freeing the config, we make sure we flush the values */
+ must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config10"));
+ must_pass(git_config_set_int(cfg, "section.tmp", 5));
+ must_pass(git_config_get_int(cfg, "section.tmp", &i));
+ must_be_true(i == 5);
+ must_pass(git_config_del(cfg, "section.tmp"));
+ git_config_free(cfg);
+END_TEST
+
BEGIN_SUITE(config)
ADD_TEST(config0);
ADD_TEST(config1);
@@ -248,4 +310,9 @@ BEGIN_SUITE(config)
ADD_TEST(config9);
ADD_TEST(config10);
ADD_TEST(config11);
+ ADD_TEST(config12);
+ ADD_TEST(config13);
+ ADD_TEST(config14);
+ ADD_TEST(config15);
+ ADD_TEST(config16);
END_SUITE
diff --git a/tests/test_helpers.c b/tests/test_helpers.c
index 760de238b..5c2ccee15 100644
--- a/tests/test_helpers.c
+++ b/tests/test_helpers.c
@@ -32,17 +32,17 @@ int write_object_data(char *file, void *data, size_t len)
git_file fd;
int ret;
- if ((fd = gitfo_creat(file, S_IREAD | S_IWRITE)) < 0)
+ if ((fd = p_creat(file, S_IREAD | S_IWRITE)) < 0)
return -1;
- ret = gitfo_write(fd, data, len);
- gitfo_close(fd);
+ ret = p_write(fd, data, len);
+ p_close(fd);
return ret;
}
int write_object_files(const char *odb_dir, object_data *d)
{
- if (gitfo_mkdir(odb_dir, 0755) < 0) {
+ if (p_mkdir(odb_dir, 0755) < 0) {
int err = errno;
fprintf(stderr, "can't make directory \"%s\"", odb_dir);
if (err == EEXIST)
@@ -51,7 +51,7 @@ int write_object_files(const char *odb_dir, object_data *d)
return -1;
}
- if ((gitfo_mkdir(d->dir, 0755) < 0) && (errno != EEXIST)) {
+ if ((p_mkdir(d->dir, 0755) < 0) && (errno != EEXIST)) {
fprintf(stderr, "can't make object directory \"%s\"\n", d->dir);
return -1;
}
@@ -65,16 +65,16 @@ int write_object_files(const char *odb_dir, object_data *d)
int remove_object_files(const char *odb_dir, object_data *d)
{
- if (gitfo_unlink(d->file) < 0) {
+ if (p_unlink(d->file) < 0) {
fprintf(stderr, "can't delete object file \"%s\"\n", d->file);
return -1;
}
- if ((gitfo_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) {
+ if ((p_rmdir(d->dir) < 0) && (errno != ENOTEMPTY)) {
fprintf(stderr, "can't remove object directory \"%s\"\n", d->dir);
return -1;
}
- if (gitfo_rmdir(odb_dir) < 0) {
+ if (p_rmdir(odb_dir) < 0) {
fprintf(stderr, "can't remove directory \"%s\"\n", odb_dir);
return -1;
}
@@ -104,14 +104,14 @@ int remove_loose_object(const char *repository_folder, git_object *object)
ptr += GIT_OID_HEXSZ + 1;
*ptr = 0;
- if (gitfo_unlink(full_path) < 0) {
+ if (p_unlink(full_path) < 0) {
fprintf(stderr, "can't delete object file \"%s\"\n", full_path);
return -1;
}
*top_folder = 0;
- if ((gitfo_rmdir(full_path) < 0) && (errno != ENOTEMPTY)) {
+ if ((p_rmdir(full_path) < 0) && (errno != ENOTEMPTY)) {
fprintf(stderr, "can't remove object directory \"%s\"\n", full_path);
return -1;
}
@@ -134,44 +134,44 @@ int cmp_objects(git_rawobj *o, object_data *d)
int copy_file(const char *src, const char *dst)
{
- gitfo_buf source_buf;
+ git_fbuffer source_buf;
git_file dst_fd;
int error = GIT_ERROR;
- if (gitfo_read_file(&source_buf, src) < GIT_SUCCESS)
+ if (git_futils_readbuffer(&source_buf, src) < GIT_SUCCESS)
return GIT_ENOTFOUND;
- dst_fd = gitfo_creat_force(dst, 0644);
+ dst_fd = git_futils_creat_withpath(dst, 0644);
if (dst_fd < 0)
goto cleanup;
- error = gitfo_write(dst_fd, source_buf.data, source_buf.len);
+ error = p_write(dst_fd, source_buf.data, source_buf.len);
cleanup:
- gitfo_free_buf(&source_buf);
- gitfo_close(dst_fd);
+ git_futils_freebuffer(&source_buf);
+ p_close(dst_fd);
return error;
}
int cmp_files(const char *a, const char *b)
{
- gitfo_buf buf_a, buf_b;
+ git_fbuffer buf_a, buf_b;
int error = GIT_ERROR;
- if (gitfo_read_file(&buf_a, a) < GIT_SUCCESS)
+ if (git_futils_readbuffer(&buf_a, a) < GIT_SUCCESS)
return GIT_ERROR;
- if (gitfo_read_file(&buf_b, b) < GIT_SUCCESS) {
- gitfo_free_buf(&buf_a);
+ if (git_futils_readbuffer(&buf_b, b) < GIT_SUCCESS) {
+ git_futils_freebuffer(&buf_a);
return GIT_ERROR;
}
if (buf_a.len == buf_b.len && !memcmp(buf_a.data, buf_b.data, buf_a.len))
error = GIT_SUCCESS;
- gitfo_free_buf(&buf_a);
- gitfo_free_buf(&buf_b);
+ git_futils_freebuffer(&buf_a);
+ git_futils_freebuffer(&buf_b);
return error;
}
@@ -182,11 +182,11 @@ static int remove_filesystem_element_recurs(void *GIT_UNUSED(nil), char *path)
GIT_UNUSED_ARG(nil);
- error = gitfo_isdir(path);
+ error = git_futils_isdir(path);
if (error == GIT_SUCCESS) {
size_t root_size = strlen(path);
- error = gitfo_dirent(path, GIT_PATH_MAX, remove_filesystem_element_recurs, NULL);
+ error = git_futils_direach(path, GIT_PATH_MAX, remove_filesystem_element_recurs, NULL);
if (error < GIT_SUCCESS)
return error;
@@ -194,7 +194,7 @@ static int remove_filesystem_element_recurs(void *GIT_UNUSED(nil), char *path)
return rmdir(path);
}
- return gitfo_unlink(path);
+ return p_unlink(path);
}
int rmdir_recurs(const char *directory_path)
@@ -214,10 +214,10 @@ static int copy_filesystem_element_recurs(void *_data, char *source)
copydir_data *data = (copydir_data *)_data;
data->dst[data->dst_len] = 0;
- git__joinpath(data->dst, data->dst, source + data->src_len);
+ git_path_join(data->dst, data->dst, source + data->src_len);
- if (gitfo_isdir(source) == GIT_SUCCESS)
- return gitfo_dirent(source, GIT_PATH_MAX, copy_filesystem_element_recurs, _data);
+ if (git_futils_isdir(source) == GIT_SUCCESS)
+ return git_futils_direach(source, GIT_PATH_MAX, copy_filesystem_element_recurs, _data);
return copy_file(source, data->dst);
}
@@ -229,13 +229,14 @@ int copydir_recurs(const char *source_directory_path, const char *destination_di
copydir_data data;
/* Source has to exist, Destination hast to _not_ exist */
- if (gitfo_isdir(source_directory_path) || !gitfo_isdir(destination_directory_path))
+ if (git_futils_isdir(source_directory_path) != GIT_SUCCESS ||
+ git_futils_isdir(destination_directory_path) == GIT_SUCCESS)
return GIT_EINVALIDPATH;
- git__joinpath(source_buffer, source_directory_path, "");
+ git_path_join(source_buffer, source_directory_path, "");
data.src_len = strlen(source_buffer);
- git__joinpath(dest_buffer, destination_directory_path, "");
+ git_path_join(dest_buffer, destination_directory_path, "");
data.dst = dest_buffer;
data.dst_len = strlen(dest_buffer);
@@ -262,14 +263,14 @@ static int remove_placeholders_recurs(void *filename, char *path)
char passed_filename[GIT_PATH_MAX];
char *data = (char *)filename;
- if (!gitfo_isdir(path))
- return gitfo_dirent(path, GIT_PATH_MAX, remove_placeholders_recurs, data);
+ if (!git_futils_isdir(path))
+ return git_futils_direach(path, GIT_PATH_MAX, remove_placeholders_recurs, data);
- if (git__basename_r(passed_filename, sizeof(passed_filename), path) < GIT_SUCCESS)
- return GIT_EINVALIDPATH;
+ if (git_path_basename_r(passed_filename, sizeof(passed_filename), path) < GIT_SUCCESS)
+ return GIT_EINVALIDPATH;
if (!strcmp(data, passed_filename))
- return gitfo_unlink(path);
+ return p_unlink(path);
return GIT_SUCCESS;
}
@@ -278,7 +279,7 @@ int remove_placeholders(char *directory_path, char *filename)
{
char buffer[GIT_PATH_MAX];
- if (gitfo_isdir(directory_path))
+ if (git_futils_isdir(directory_path))
return GIT_EINVALIDPATH;
strcpy(buffer, directory_path);
diff --git a/tests/test_lib.c b/tests/test_lib.c
index aaacdff65..a4c39dfde 100755
--- a/tests/test_lib.c
+++ b/tests/test_lib.c
@@ -15,8 +15,7 @@ struct git_test {
char *message;
char *failed_pos;
char *description;
-
- int ret_value;
+ char *error_message;
git_testfunc function;
unsigned failed:1, ran:1;
@@ -36,6 +35,7 @@ static void test_free(git_test *t)
free(t->description);
free(t->failed_pos);
free(t->message);
+ free(t->error_message);
free(t);
}
}
@@ -57,15 +57,8 @@ static git_test *create_test(git_testfunc function)
{
git_test *t = DO_ALLOC(git_test);
- t->name = NULL;
- t->failed = 0;
- t->ran = 0;
- t->description = NULL;
- t->message = NULL;
- t->ret_value = 0;
- t->failed_pos = NULL;
+ memset(t, 0x0, sizeof(git_test));
t->function = function;
- t->jump = NULL;
return t;
}
@@ -81,36 +74,39 @@ void git_test__init(git_test *t, const char *name, const char *description)
* Public assert methods
*-------------------------------------------------------------------------*/
-static void fail_test(git_test *tc, const char *file, int line, const char *message, int ret_value)
+static void fail_test(git_test *tc, const char *file, int line, const char *message)
{
char buf[1024];
+ const char *last_error = git_lasterror();
snprintf(buf, 1024, "%s:%d", file, line);
tc->failed = 1;
tc->message = strdup(message);
- tc->ret_value = ret_value;
tc->failed_pos = strdup(buf);
+ if (last_error)
+ tc->error_message = strdup(last_error);
+
if (tc->jump != 0)
longjmp(*(tc->jump), 0);
}
void git_test__fail(git_test *tc, const char *file, int line, const char *message)
{
- fail_test(tc, file, line, message, 0);
+ fail_test(tc, file, line, message);
}
void git_test__assert(git_test *tc, const char *file, int line, const char *message, int condition)
{
if (condition == 0)
- fail_test(tc, file, line, message, 0);
+ fail_test(tc, file, line, message);
}
void git_test__assert_pass(git_test *tc, const char *file, int line, const char *message, int ret_value)
{
if (ret_value < 0)
- fail_test(tc, file, line, message, ret_value);
+ fail_test(tc, file, line, message);
}
/*-------------------------------------------------------------------------*
@@ -167,8 +163,8 @@ static void print_details(git_testsuite *ts)
failCount++;
printf(" %d) \"%s\" [test %s @ %s]\n\t%s\n",
failCount, tc->description, tc->name, tc->failed_pos, tc->message);
- if (tc->ret_value)
- printf("\tError: (%d) %s\n", tc->ret_value, git_lasterror());
+ if (tc->error_message)
+ printf("\tError: %s\n", tc->error_message);
}
}
}
diff --git a/tests/test_lib.h b/tests/test_lib.h
index f3febe857..fc75ed771 100755
--- a/tests/test_lib.h
+++ b/tests/test_lib.h
@@ -15,7 +15,7 @@
#define BEGIN_SUITE(SNAME) \
git_testsuite *libgit2_suite_##SNAME(void) {\
git_testsuite *_gitsuite = git_testsuite_new(#SNAME);
-
+
#define ADD_TEST(TNAME) \
git_testsuite_add(_gitsuite, _gittest__##TNAME);
@@ -26,6 +26,7 @@
#define BEGIN_TEST(TNAME, DESC) \
static void _gittest__##TNAME(git_test *_gittest) { \
git_test__init(_gittest, #TNAME, DESC); \
+ git_clearerror();\
{\
#define END_TEST }}