diff options
| -rw-r--r-- | CMakeLists.txt | 63 | ||||
| -rw-r--r-- | README.md | 89 | ||||
| -rw-r--r-- | api.docurium | 13 | ||||
| -rw-r--r-- | api.doxygen | 24 | ||||
| -rw-r--r-- | examples/.gitignore | 2 | ||||
| -rw-r--r-- | examples/Makefile | 10 | ||||
| -rw-r--r-- | examples/general.c | 439 | ||||
| -rw-r--r-- | examples/showindex.c | 43 | ||||
| -rw-r--r-- | include/git2/odb_backend.h | 2 | ||||
| -rw-r--r-- | include/git2/oid.h | 4 | ||||
| -rw-r--r-- | src/backends/hiredis.c | 217 | ||||
| -rw-r--r-- | src/backends/sqlite.c | 296 | ||||
| -rw-r--r-- | src/blob.c | 4 | ||||
| -rw-r--r-- | src/common.h | 1 | ||||
| -rw-r--r-- | src/fileops.c | 2 | ||||
| -rw-r--r-- | src/oid.c | 2 | ||||
| -rw-r--r-- | tests/t06-index.c | 43 | ||||
| -rw-r--r-- | tests/t11-sqlite.c | 126 | ||||
| -rw-r--r-- | tests/t14-hiredis.c | 123 | ||||
| -rw-r--r-- | tests/test_main.c | 4 | ||||
| -rwxr-xr-x | waf | bin | 76176 -> 0 bytes | |||
| -rw-r--r-- | wscript | 284 |
22 files changed, 589 insertions, 1202 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index acac2a6de..e56ace2da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,49 +24,26 @@ SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${ # Find required dependencies INCLUDE_DIRECTORIES(deps/zlib src include) -# Try finding openssl -FIND_PACKAGE(OpenSSL) -IF (OPENSSL_CRYPTO_LIBRARIES) - SET(SHA1_TYPE "openssl" CACHE STRING "Which SHA1 implementation to use: builtin, ppc, openssl") -ELSEIF () - SET(SHA1_TYPE "builtin" CACHE STRING "Which SHA1 implementation to use: builtin, ppc") -ENDIF () - -INCLUDE(FindPkgConfig) - -# Show SQLite3 settings in GUI (if they won't be found out) -SET(SQLITE3_INCLUDE_DIRS "" CACHE PATH "SQLite include directory") -SET(SQLITE3_LIBRARIES "" CACHE FILEPATH "SQLite library") - -# Are SQLite3 variables already set up? (poor Windows/no pkg-config/no sqlite3.pc) -IF (SQLITE3_INCLUDE_DIRS AND SQLITE3_LIBRARIES) - SET(SQLITE3_FOUND 1) -ENDIF () - -# Try to find SQLite3 via pkg-config -IF (PKG_CONFIG_FOUND AND NOT SQLITE3_FOUND) - pkg_check_modules(SQLITE3 sqlite3) -ENDIF () - -# Compile SQLite backend if SQLite3 is available -IF (SQLITE3_FOUND) - ADD_DEFINITIONS(-DGIT2_SQLITE_BACKEND) - INCLUDE_DIRECTORIES(${SQLITE3_INCLUDE_DIRS}) -ENDIF () - # Installation paths SET(INSTALL_BIN bin CACHE PATH "Where to install binaries to.") SET(INSTALL_LIB lib CACHE PATH "Where to install libraries to.") SET(INSTALL_INC include CACHE PATH "Where to install headers to.") # Build options -OPTION (BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON) +OPTION (BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" OFF) OPTION (BUILD_TESTS "Build Tests" ON) OPTION (THREADSAFE "Build libgit2 as threadsafe" OFF) +# Platform specific compilation flags +IF (MSVC) + SET(CMAKE_C_FLAGS "/TC /W4 /WX /nologo /Zi") + SET(CMAKE_C_FLAGS_DEBUG "/Od /RTC1 /RTCc /DEBUG /MTd") + SET(CMAKE_C_FLAGS_RELEASE "/MT /O2") +ENDIF() + # Build Release by default IF (NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) + SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) ENDIF () IF (THREADSAFE) @@ -90,20 +67,9 @@ IF (WIN32 AND NOT CYGWIN) FILE(GLOB SRC_PLAT src/win32/*.c) ENDIF () -# Specify sha1 implementation -IF (SHA1_TYPE STREQUAL "ppc") - ADD_DEFINITIONS(-DPPC_SHA1) - FILE(GLOB SRC_SHA1 src/ppc/*.c) -ELSEIF (SHA1_TYPE STREQUAL "openssl") - ADD_DEFINITIONS(-DOPENSSL_SHA1) - SET (SRC_SHA1) - INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) - SET (LIB_SHA1 ${OPENSSL_CRYPTO_LIBRARIES}) -ENDIF () - # Compile and link libgit2 ADD_LIBRARY(git2 ${SRC} ${SRC_PLAT} ${SRC_SHA1} ${SRC_ZLIB}) -TARGET_LINK_LIBRARIES(git2 ${LIB_SHA1} ${CMAKE_THREAD_LIBS_INIT} ${SQLITE3_LIBRARIES}) +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}) @@ -118,16 +84,15 @@ INSTALL(FILES include/git2.h DESTINATION ${INSTALL_INC} ) # Tests IF (BUILD_TESTS) - SET(TEST_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources" CACHE PATH "Path to test resources.") + SET(TEST_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources" CACHE PATH "Path to test resources.") ADD_DEFINITIONS(-DTEST_RESOURCES=\"${TEST_RESOURCES}\") - - ENABLE_TESTING() - INCLUDE_DIRECTORIES(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}) - TARGET_LINK_LIBRARIES(libgit2_test ${LIB_SHA1} ${CMAKE_THREAD_LIBS_INIT} ${SQLITE3_LIBRARIES}) + TARGET_LINK_LIBRARIES(libgit2_test ${CMAKE_THREAD_LIBS_INIT}) + ENABLE_TESTING() ADD_TEST(libgit2_test libgit2_test) ENDIF () @@ -20,85 +20,27 @@ What It Can Do libgit2 is already very usable. * SHA conversions, formatting and shortening -* object reading (loose and packed) -* object writing (loose) -* commit, tag, tree and blob parsing and write-back +* abstracked ODB backend system +* commit, tag, tree and blob parsing, editing, and write-back * tree traversal * revision walking * index file (staging area) manipulation -* custom ODB backends * reference management (including packed references) -* ...and more +* config file management +* high level repository management +* thread safety and reentrancy +* descriptive and detailed error messages +* ...and more (over 175 different API calls) - -Building libgit2 - External dependencies -======================================== +Building libgit2 - Using CMake +============================== libgit2 builds cleanly on most platforms without any external dependencies. -Under Unix-like systems, like Linux, *BSD and Mac OS X, libgit2 expects `pthreads` to be available; +Under Unix-like systems, like Linux, * BSD and Mac OS X, libgit2 expects `pthreads` to be available; they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API for threading. -Additionally, the following libraries may be used as replacement for built-in functionality: - -* LibSSL **(optional)** <http://www.openssl.org/> - -libgit2 can be built using the SHA1 implementation of LibSSL-Crypto, instead of the built-in custom implementations. Performance wise, they are quite similar. - -Building libgit2 - Using waf -====================== - -Waf is a minimalist build system which only requires a Python 2.5+ interpreter to run. This is the default build system for libgit2. - -To build libgit2 using waf, first configure the build system by running: - - $ ./waf configure - -Then build the library, either in its shared (libgit2.so) or static form (libgit2.a): - - $ ./waf build-static - $ ./waf build-shared - -You can then run the full test suite with: - - $ ./waf test - -And finally you can install the library with (you may need to sudo): - - $ sudo ./waf install - -The waf build system for libgit2 accepts the following flags: - - --debug - build the library with debug symbols. - Defaults to off. - - --sha1=[builtin|ppc|openssl] - use the builtin SHA1 functions, the optimized PPC versions - or the SHA1 functions from LibCrypto (OpenSSL). - Defaults to 'builtin'. - - --msvc=[7.1|8.0|9.0|10.0] - Force a specific version of the MSVC compiler, if more than - one version is installed. - - --arch=[ia64|x64|x86|x86_amd64|x86_ia64] - Force a specific architecture for compilers that support it. - - --with-sqlite - Enable sqlite support. - - --with-redis - Enable redis support. - -You can run `./waf --help` to see a full list of install options and -targets. - - -Building libgit2 - Using CMake -============================== - -The libgit2 library can also be built using CMake 2.6+ (<http://www.cmake.org>) on all platforms. +The libgit2 library is built using CMake 2.6+ (<http://www.cmake.org>) on all platforms. On most systems you can build the library using the following commands @@ -115,6 +57,14 @@ To install the library you can specify the install prefix by setting: For more advanced use or questions about CMake please read <http://www.cmake.org/Wiki/CMake_FAQ>. +The following CMake variables are declared: + +- `INSTALL_BIN`: Where to install binaries to. +- `INSTALL_LIB`: Where to install libraries to. +- `INSTALL_INC`: Where to install headers to. +- `BUILD_SHARED_LIBS`: Build libgit2 as a Shared Library (defaults to OFF) +- `BUILD_TESTS`: Build the libgit2 test suite (defaults to ON) +- `THREADSAFE`: Build libgit2 with threading support (defaults to OFF) Language Bindings ================================== @@ -134,6 +84,7 @@ Here are the bindings to libgit2 that are currently available: * libqgit2 (C++ QT bindings) <https://projects.kde.org/projects/playground/libs/libqgit2/> * libgit2-ocaml (ocaml bindings) <https://github.com/burdges/libgit2-ocaml> * Geef (Erlang bindings) <https://github.com/schacon/geef> +* libgit2net (.NET bindings, low level) <https://github.com/txdv/libgit2net> If you start another language binding to libgit2, please let us know so we can add it to the list. diff --git a/api.docurium b/api.docurium new file mode 100644 index 000000000..9e17817db --- /dev/null +++ b/api.docurium @@ -0,0 +1,13 @@ +{ + "name": "libgit2", + "github": "libgit2/libgit2", + "input": "include/git2", + "prefix": "git_", + "output": "docs", + "branch": "gh-pages", + "examples": "examples", + "legacy": { + "input": {"src/git": ["v0.1.0"], + "src/git2": ["v0.2.0", "v0.3.0"]} + } +} diff --git a/api.doxygen b/api.doxygen deleted file mode 100644 index b812add85..000000000 --- a/api.doxygen +++ /dev/null @@ -1,24 +0,0 @@ -PROJECT_NAME = libgit2 - -INPUT = include/git2 -QUIET = YES -RECURSIVE = YES -FILE_PATTERNS = *.h -OUTPUT_DIRECTORY = apidocs -GENERATE_TAGFILE = apidocs/libgit2.tag - -JAVADOC_AUTOBRIEF = YES -MACRO_EXPANSION = YES -EXPAND_ONLY_PREDEF = YES -OPTIMIZE_OUTPUT_FOR_C = YES -STRIP_CODE_COMMENTS = NO -FULL_PATH_NAMES = NO -CASE_SENSE_NAMES = NO - -PREDEFINED = \ - "GIT_EXTERN(x)=x" \ - "GIT_EXTERN_TLS(x)=x" \ - "GIT_INLINE(x)=x" \ - "GIT_BEGIN_DECL=" \ - "GIT_END_DECL=" \ - DOXYGEN= diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 000000000..4c34e4ab5 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,2 @@ +general +showindex diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 000000000..f7bf469a5 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,10 @@ +all: general showindex + +general : general.c + gcc -lgit2 -o general general.c + +showindex : showindex.c + gcc -lgit2 -o showindex showindex.c + +clean: + rm general showindex diff --git a/examples/general.c b/examples/general.c new file mode 100644 index 000000000..6362e9650 --- /dev/null +++ b/examples/general.c @@ -0,0 +1,439 @@ +// [**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. +// +// 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 +// new functionality. +// +// If you're trying to write something in C using [libgit2][lg], you will also want +// to check out the generated [API documentation][ap] and the [Usage Guide][ug]. We've +// tried to link to the relevant sections of the API docs in each section in this file. +// +// **libgit2** only implements the core plumbing functions, not really the higher +// level porcelain stuff. For a primer on Git Internals that you will need to know +// to work with Git at this level, check out [Chapter 9][pg] of the Pro Git book. +// +// [lg]: http://libgit2.github.com +// [ap]: http://libgit2.github.com/libgit2 +// [ug]: http://libgit2.github.com/api.html +// [pg]: http://progit.org/book/ch9-0.html + +// ### Includes + +// Including the `git2.h` header will include all the other libgit2 headers that you need. +// It should be the only thing you need to include in order to compile properly and get +// all the libgit2 API. +#include <git2.h> +#include <stdio.h> + +int main (int argc, char** argv) +{ + // ### Opening the Repository + + // There are a couple of methods for opening a repository, this being the simplest. + // There are also [methods][me] for specifying the index file and work tree locations, here + // we are assuming they are in the normal places. + // + // [me]: http://libgit2.github.com/libgit2/#HEAD/group/repository + git_repository *repo; + git_repository_open(&repo, "/opt/libgit2-test/.git"); + + // ### SHA-1 Value Conversions + + // For our first example, we will convert a 40 character hex value to the 20 byte raw SHA1 value. + printf("*Hex to Raw*\n"); + char hex[] = "fd6e612585290339ea8bf39c692a7ff6a29cb7c3"; + + // The `git_oid` is the structure that keeps the SHA value. We will use this throughout the example + // for storing the value of the current SHA key we're working with. + git_oid oid; + git_oid_mkstr(&oid, hex); + + // Once we've converted the string into the oid value, we can get the raw value of the SHA. + printf("Raw 20 bytes: [%s]\n", (&oid)->id); + + // Next we will convert the 20 byte raw SHA1 value to a human readable 40 char hex value. + printf("\n*Raw to Hex*\n"); + char out[41]; + out[40] = '\0'; + + // If you have a oid, you can easily get the hex value of the SHA as well. + git_oid_fmt(out, &oid); + printf("SHA hex string: %s\n", out); + + // ### 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 + // repository. + // [odb]: http://libgit2.github.com/libgit2/#HEAD/group/odb + git_odb *odb; + odb = git_repository_database(repo); + + // #### Raw Object Reading + + printf("\n*Raw Object Read*\n"); + git_odb_object *obj; + git_otype otype; + const unsigned char *data; + const char *str_type; + int error; + + // We can read raw objects directly from the object database if we have the oid (SHA) + // of the object. This allows us to access objects without knowing thier type and inspect + // the raw bytes unparsed. + error = git_odb_read(&obj, odb, &oid); + + // A raw object only has three properties - the type (commit, blob, tree or tag), the size + // of the raw data and the raw, unparsed data itself. For a commit or tag, that raw data + // is human readable plain ASCII text. For a blob it is just file contents, so it could be + // text or binary data. For a tree it is a special binary format, so it's unlikely to be + // hugely helpful as a raw object. + 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 + // representation of that value (and vice-versa). + str_type = git_object_type2string(otype); + printf("object length and type: %d, %s\n", + (int)git_odb_object_size(obj), + str_type); + + // For proper memory management, close the object when you are done with it or it will leak + // memory. + git_odb_object_close(obj); + + // #### Raw Object Writing + + printf("\n*Raw Object Write*\n"); + + // You can also write raw object data to Git. This is pretty cool because it gives you + // direct access to the key/value properties of Git. Here we'll write a new blob object + // that just contains a simple string. Notice that we have to specify the object type as + // the `git_otype` enum. + git_odb_write(&oid, odb, "test data", sizeof("test data") - 1, GIT_OBJ_BLOB); + + // Now that we've written the object, we can check out what SHA1 was generated when the + // object was written to our database. + git_oid_fmt(out, &oid); + printf("Written Object: %s\n", out); + + // ### Object Parsing + // libgit2 has methods to parse every object type in Git so you don't have to work directly + // with the raw data. This is much faster and simpler than trying to deal with the raw data + // yourself. + + // #### Commit Parsing + // [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 + + printf("\n*Commit Parsing*\n"); + + git_commit *commit; + git_oid_mkstr(&oid, "f0877d0b841d75172ec404fc9370173dfffc20d1"); + + error = git_commit_lookup(&commit, repo, &oid); + + const git_signature *author, *cmtter; + const char *message, *message_short; + time_t ctime; + unsigned int parents, p; + + // Each of the properties of the commit object are accessible via methods, including commonly + // needed variations, such as `git_commit_time` which returns the author time and `_message_short` + // which gives you just the first line of the commit message. + message = git_commit_message(commit); + message_short = git_commit_message_short(commit); + author = git_commit_author(commit); + cmtter = git_commit_committer(commit); + ctime = git_commit_time(commit); + + // The author and committer methods return [git_signature] structures, which give you name, email + // and `when`, which is a `git_time` structure, giving you a timestamp and timezone offset. + 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. + // 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++) { + git_commit *parent; + git_commit_parent(&parent, commit, p); + git_oid_fmt(out, git_commit_id(parent)); + printf("Parent: %s\n", out); + git_commit_close(parent); + } + + // Don't forget to close the object to prevent memory leaks. You will have to do this for + // all the objects you open and parse. + git_commit_close(commit); + + // #### Writing Commits + // + // libgit2 provides a couple of methods to create commit objects easily as well. There are four + // different create signatures, we'll just show one of them here. You can read about the other + // ones in the [commit API docs][cd]. + // [cd]: http://libgit2.github.com/libgit2/#HEAD/group/commit + + printf("\n*Commit Writing*\n"); + git_oid tree_id, parent_id, commit_id; + + // Creating signatures for an authoring identity and time is pretty simple - you will need to have + // this to create a commit in order to specify who created it and when. Default values for the name + // and email should be found in the `user.name` and `user.email` configuration options. See the `config` + // section of this example file to see how to access config values. + author = git_signature_new("Scott Chacon", "schacon@gmail.com", + 123456789, 60); + cmtter = git_signature_new("Scott A Chacon", "scott@github.com", + 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 + git_oid_mkstr(&tree_id, "28873d96b4e8f4e33ea30f4c682fd325f7ba56ac"); + git_oid_mkstr(&parent_id, "f0877d0b841d75172ec404fc9370173dfffc20d1"); + + // Here we actually create the commit object with a single call with all the values we need to create + // the commit. The SHA key is written to the `commit_id` variable here. + git_commit_create_v( + &commit_id, /* out id */ + repo, + NULL, /* do not update the HEAD */ + author, + cmtter, + "example commit", + &tree_id, + 1, &parent_id); + + // Now we can take a look at the commit SHA we've generated. + git_oid_fmt(out, &commit_id); + printf("New Commit: %s\n", out); + + // #### Tag Parsing + // You can parse and create tags with the [tag management API][tm], which functions very similarly + // to the commit lookup, parsing and creation methods, since the objects themselves are very similar. + // [tm]: http://libgit2.github.com/libgit2/#HEAD/group/tag + printf("\n*Tag Parsing*\n"); + git_tag *tag; + const char *tmessage, *tname; + git_otype ttype; + + // We create an oid for the tag object if we know the SHA and look it up in the repository the same + // way that we would a commit (or any other) object. + git_oid_mkstr(&oid, "bc422d45275aca289c51d79830b45cecebff7c3a"); + + 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'), + // 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" + ttype = git_tag_type(tag); // GIT_OBJ_COMMIT (otype enum) + tmessage = git_tag_message(tag); // "tag message\n" + printf("Tag Message: %s\n", tmessage); + + git_commit_close(commit); + + // #### Tree Parsing + // [Tree parsing][tp] is a bit different than the other objects, in that we have a subtype which is the + // tree entry. This is not an actual object type in Git, but a useful structure for parsing and + // traversing tree entries. + // + // [tp]: http://libgit2.github.com/libgit2/#HEAD/group/tree + printf("\n*Tree Parsing*\n"); + + git_tree *tree; + const git_tree_entry *entry; + git_object *objt; + + // Create the oid and lookup the tree object just like the other objects. + git_oid_mkstr(&oid, "2a741c18ac5ff082a7caaec6e74db3075a1906b5"); + git_tree_lookup(&tree, repo, &oid); + + // Getting the count of entries in the tree so you can iterate over them if you want to. + int cnt = git_tree_entrycount(tree); // 3 + printf("tree entries: %d\n", cnt); + + entry = git_tree_entry_byindex(tree, 0); + printf("Entry name: %s\n", git_tree_entry_name(entry)); // "hello.c" + + // You can also access tree entries by name if you know the name of the entry you're looking for. + entry = git_tree_entry_byname(tree, "hello.c"); + git_tree_entry_name(entry); // "hello.c" + + // Once you have the entry object, you can access the content or subtree (or commit, in the case + // of submodules) that it points to. You can also get the mode if you want. + git_tree_entry_2object(&objt, repo, entry); // blob + + // Remember to close the looked-up object once you are done using it + git_object_close(objt); + + // #### Blob Parsing + // + // 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 + // 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. + // + // [ba]: http://libgit2.github.com/libgit2/#HEAD/group/blob + + printf("\n*Blob Parsing*\n"); + git_blob *blob; + + git_oid_mkstr(&oid, "af7574ea73f7b166f869ef1a39be126d9a186ae0"); + git_blob_lookup(&blob, repo, &oid); + + // You can access a buffer with the raw contents of the blob directly. + // Note that this buffer may not be contain ASCII data for certain blobs (e.g. binary files): + // do not consider the buffer a NULL-terminated string, and use the `git_blob_rawsize` attribute to + // find out its exact size in bytes + printf("Blob Size: %d\n", git_blob_rawsize(blob)); // 8 + git_blob_rawcontent(blob); // "content" + + // ### Revwalking + // + // The libgit2 [revision walking api][rw] provides methods to traverse the directed graph created + // by the parent pointers of the commit objects. Since all commits point back to the commit that + // came directly before them, you can walk this parentage as a graph and find all the commits that + // were ancestors of (reachable from) a given starting point. This can allow you to create `git log` + // type functionality. + // + // [rw]: http://libgit2.github.com/libgit2/#HEAD/group/revwalk + + printf("\n*Revwalking*\n"); + git_revwalk *walk; + git_commit *wcommit; + + git_oid_mkstr(&oid, "f0877d0b841d75172ec404fc9370173dfffc20d1"); + + // To use the revwalker, create a new walker, tell it how you want to sort the output and then push + // one or more starting points onto the walker. If you want to emulate the output of `git log` you + // would push the SHA of the commit that HEAD points to into the walker and then start traversing them. + // You can also 'hide' commits that you want to stop at or not see any of their ancestors. So if you + // want to emulate `git log branch1..branch2`, you would push the oid of `branch2` and hide the oid + // of `branch1`. + git_revwalk_new(&walk, repo); + git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE); + git_revwalk_push(walk, &oid); + + const git_signature *cauth; + const char *cmsg; + + // Now that we have the starting point pushed onto the walker, we can start asking for ancestors. It + // will return them in the sorting order we asked for as commit oids. + // We can then lookup and parse the commited pointed at by the returned OID; + // note that this operation is specially fast since the raw contents of the commit object will + // be cached in memory + while ((git_revwalk_next(&oid, walk)) == GIT_SUCCESS) { + error = git_commit_lookup(&wcommit, repo, &oid); + cmsg = git_commit_message_short(wcommit); + cauth = git_commit_author(wcommit); + printf("%s (%s)\n", cmsg, cauth->email); + git_commit_close(wcommit); + } + + // Like the other objects, be sure to free the revwalker when you're done to prevent memory leaks. + // Also, make sure that the repository being walked it not deallocated while the walk is in + // progress, or it will result in undefined behavior + git_revwalk_free(walk); + + // ### Index File Manipulation + // + // 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 + + printf("\n*Index Walking*\n"); + + git_index *index; + unsigned int i, e, ecount; + + // You can either open the index from the standard location in an open repository, as we're doing + // here, or you can open and manipulate any index file with `git_index_open_bare()`. The index + // for the repository will be located and loaded from disk. + git_repository_index(&index, repo); + + // For each entry in the index, you can get a bunch of information including the SHA (oid), path + // and mode which map to the tree objects that are written out. It also has filesystem properties + // to help determine what to inspect for changes (ctime, mtime, dev, ino, uid, gid, file_size and flags) + // All these properties are exported publicly in the `git_index_entry` struct + ecount = git_index_entrycount(index); + for (i = 0; i < ecount; ++i) { + git_index_entry *e = git_index_get(index, i); + + printf("path: %s\n", e->path); + printf("mtime: %d\n", (int)e->mtime.seconds); + printf("fs: %d\n", (int)e->file_size); + } + + git_index_free(index); + + // ### References + // + // The [reference API][ref] allows you to list, resolve, create and update references such as + // branches, tags and remote references (everything in the .git/refs directory). + // + // [ref]: http://libgit2.github.com/libgit2/#HEAD/group/reference + + printf("\n*Reference Listing*\n"); + + // Here we will implement something like `git for-each-ref` simply listing out all available + // references and the object SHA they resolve to. + git_strarray ref_list; + git_reference_listall(&ref_list, repo, GIT_REF_LISTALL); + + const char *refname, *reftarget; + git_reference *ref; + + // Now that we have the list of reference names, we can lookup each ref one at a time and + // resolve them to the SHA, then print both values out. + for (i = 0; i < ref_list.count; ++i) { + refname = ref_list.strings[i]; + git_reference_lookup(&ref, repo, refname); + + switch (git_reference_type(ref)) { + case GIT_REF_OID: + git_oid_fmt(out, git_reference_oid(ref)); + printf("%s [%s]\n", refname, out); + break; + + case GIT_REF_SYMBOLIC: + printf("%s => %s\n", refname, git_reference_target(ref)); + break; + } + } + + git_strarray_free(&ref_list); + + // ### Config Files + // + // The [config API][config] allows you to list and updatee config values in + // any of the accessible config file locations (system, global, local). + // + // [config]: http://libgit2.github.com/libgit2/#HEAD/group/config + + printf("\n*Config Listing*\n"); + + const char *email; + int j; + + git_config *cfg; + + // Open a config object so we can read global values from it. + git_config_open_global(&cfg); + + git_config_get_int(cfg, "help.autocorrect", &j); + printf("Autocorrect: %d\n", j); + + git_config_get_string(cfg, "user.email", &email); + printf("Email: %s\n", email); + + // Finally, when you're done with the repository, you can free it as well. + git_repository_free(repo); +} + diff --git a/examples/showindex.c b/examples/showindex.c new file mode 100644 index 000000000..7f2130b90 --- /dev/null +++ b/examples/showindex.c @@ -0,0 +1,43 @@ +#include <git2.h> +#include <stdio.h> + +int main (int argc, char** argv) +{ + git_repository *repo; + git_index *index; + unsigned int i, e, ecount; + git_index_entry **entries; + git_oid oid; + + char out[41]; + out[40] = '\0'; + + git_repository_open(&repo, "/opt/libgit2-test/.git"); + + git_repository_index(&index, repo); + git_index_read(index); + + ecount = git_index_entrycount(index); + for (i = 0; i < ecount; ++i) { + git_index_entry *e = git_index_get(index, i); + + oid = e->oid; + git_oid_fmt(out, &oid); + + printf("File Path: %s\n", e->path); + printf(" Blob SHA: %s\n", out); + printf("File Size: %d\n", (int)e->file_size); + printf(" Device: %d\n", (int)e->dev); + printf(" Inode: %d\n", (int)e->ino); + printf(" UID: %d\n", (int)e->uid); + printf(" GID: %d\n", (int)e->gid); + printf(" ctime: %d\n", (int)e->ctime.seconds); + printf(" mtime: %d\n", (int)e->mtime.seconds); + printf("\n"); + } + + git_index_free(index); + + git_repository_free(repo); +} + diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index 796d2b9da..43a1c2d21 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -110,10 +110,8 @@ typedef enum { GIT_STREAM_RW = (GIT_STREAM_RDONLY | GIT_STREAM_WRONLY), } git_odb_streammode; - GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir); GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir); -GIT_EXTERN(int) git_odb_backend_sqlite(git_odb_backend **backend_out, const char *sqlite_db); GIT_END_DECL diff --git a/include/git2/oid.h b/include/git2/oid.h index d87d8f6ba..3097a2d22 100644 --- a/include/git2/oid.h +++ b/include/git2/oid.h @@ -97,7 +97,7 @@ GIT_EXTERN(void) git_oid_fmt(char *str, const git_oid *oid); GIT_EXTERN(void) git_oid_pathfmt(char *str, const git_oid *oid); /** - * Format a gid_oid into a newly allocated c-string. + * Format a git_oid into a newly allocated c-string. * @param oid the oid structure to format * @return the c-string; NULL if memory is exhausted. Caller must * deallocate the string with free(). @@ -144,7 +144,7 @@ GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b); * @param b second oid structure. * @return 0 in case of a match */ -GIT_EXTERN(int) gid_oid_ncmp(unsigned int len, git_oid *a, git_oid *b); +GIT_EXTERN(int) git_oid_ncmp(unsigned int len, git_oid *a, git_oid *b); /** * OID Shortener object diff --git a/src/backends/hiredis.c b/src/backends/hiredis.c deleted file mode 100644 index 111abf7d3..000000000 --- a/src/backends/hiredis.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, - * as published by the Free Software Foundation. - * - * In addition to the permissions in the GNU General Public License, - * the authors give you unlimited permission to link the compiled - * version of this file into combinations with other programs, - * and to distribute those combinations without any restriction - * coming from the use of this file. (The General Public License - * restrictions do apply in other respects; for example, they cover - * modification of the file, and distribution when not linked into - * a combined executable.) - * - * This file is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "common.h" -#include "git2/object.h" -#include "hash.h" -#include "odb.h" - -#include "git2/odb_backend.h" - -#ifdef GIT2_HIREDIS_BACKEND - -#include <hiredis/hiredis.h> - -typedef struct { - git_odb_backend parent; - - redisContext *db; -} hiredis_backend; - -int hiredis_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) { - hiredis_backend *backend; - int error; - redisReply *reply; - - assert(len_p && type_p && _backend && oid); - - backend = (hiredis_backend *) _backend; - error = GIT_ERROR; - - reply = redisCommand(backend->db, "HMGET %b %s %s", oid->id, GIT_OID_RAWSZ, - "type", "size"); - - if (reply && reply->type == REDIS_REPLY_ARRAY) { - if (reply->element[0]->type != REDIS_REPLY_NIL && - reply->element[0]->type != REDIS_REPLY_NIL) { - *type_p = (git_otype) atoi(reply->element[0]->str); - *len_p = (size_t) atoi(reply->element[1]->str); - error = GIT_SUCCESS; - } else { - error = GIT_ENOTFOUND; - } - } else { - error = GIT_ERROR; - } - - freeReplyObject(reply); - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to read header"); -} - -int hiredis_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) { - hiredis_backend *backend; - int error; - redisReply *reply; - - assert(data_p && len_p && type_p && _backend && oid); - - backend = (hiredis_backend *) _backend; - error = GIT_ERROR; - - reply = redisCommand(backend->db, "HMGET %b %s %s %s", oid->id, GIT_OID_RAWSZ, - "type", "size", "data"); - - if (reply && reply->type == REDIS_REPLY_ARRAY) { - if (reply->element[0]->type != REDIS_REPLY_NIL && - reply->element[1]->type != REDIS_REPLY_NIL && - reply->element[2]->type != REDIS_REPLY_NIL) { - *type_p = (git_otype) atoi(reply->element[0]->str); - *len_p = (size_t) atoi(reply->element[1]->str); - *data_p = git__malloc(*len_p); - if (*data_p == NULL) { - error = GIT_ENOMEM; - } else { - memcpy(*data_p, reply->element[2]->str, *len_p); - error = GIT_SUCCESS; - } - } else { - error = GIT_ENOTFOUND; - } - } else { - error = GIT_ERROR; - } - - freeReplyObject(reply); - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to read backend"); -} - -int hiredis_backend__read_prefix(git_oid *out_oid, void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, - const git_oid *short_oid, unsigned int len) { - if (len >= GIT_OID_HEXSZ) { - /* Just match the full identifier */ - int error = hiredis_backend__read(data_p, len_p, type_p, backend, short_oid); - if (error == GIT_SUCCESS) - git_oid_cpy(out_oid, short_oid); - - return error; - } else if (len < GIT_OID_HEXSZ) { - /* TODO */ - return git__throw(GIT_ENOTIMPLEMENTED, "Hiredis backend cannot search objects from short oid"); - } -} - -int hiredis_backend__exists(git_odb_backend *_backend, const git_oid *oid) { - hiredis_backend *backend; - int found; - redisReply *reply; - - assert(_backend && oid); - - backend = (hiredis_backend *) _backend; - found = 0; - - reply = redisCommand(backend->db, "exists %b", oid->id, GIT_OID_RAWSZ); - if (reply && reply->type != REDIS_REPLY_NIL && reply->type != REDIS_REPLY_ERROR) - found = 1; - - - freeReplyObject(reply); - return found; -} - -int hiredis_backend__write(git_oid *id, git_odb_backend *_backend, const void *data, size_t len, git_otype type) { - hiredis_backend *backend; - int error; - redisReply *reply; - - assert(id && _backend && data); - - backend = (hiredis_backend *) _backend; - error = GIT_ERROR; - - if ((error = git_odb_hash(id, data, len, type)) < 0) - return git__rethrow(error, "Failed to write backend"); - - reply = redisCommand(backend->db, "HMSET %b " - "type %d " - "size %d " - "data %b ", id->id, GIT_OID_RAWSZ, - (int) type, len, data, len); - - error = (reply == NULL || reply->type == REDIS_REPLY_ERROR) ? GIT_ERROR : GIT_SUCCESS; - - freeReplyObject(reply); - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write backend"); -} - -void hiredis_backend__free(git_odb_backend *_backend) { - hiredis_backend *backend; - assert(_backend); - backend = (hiredis_backend *) _backend; - - redisFree(backend->db); - - free(backend); -} - -int git_odb_backend_hiredis(git_odb_backend **backend_out, const char *host, int port) { - hiredis_backend *backend; - - backend = git__calloc(1, sizeof (hiredis_backend)); - if (backend == NULL) - return GIT_ENOMEM; - - - backend->db = redisConnect(host, port); - if (backend->db->err) - goto cleanup; - - backend->parent.read = &hiredis_backend__read; - backend->parent.read_prefix = &hiredis_backend__read_prefix; - backend->parent.read_header = &hiredis_backend__read_header; - backend->parent.write = &hiredis_backend__write; - backend->parent.exists = &hiredis_backend__exists; - backend->parent.free = &hiredis_backend__free; - - *backend_out = (git_odb_backend *) backend; - - return GIT_SUCCESS; -cleanup: - free(backend); - return git__throw(GIT_ERROR, "Failed to get ODB backend"); -} - -#else - -int git_odb_backend_hiredis(git_odb_backend ** GIT_UNUSED(backend_out), - const char *GIT_UNUSED(host), int GIT_UNUSED(port)) { - GIT_UNUSED_ARG(backend_out); - GIT_UNUSED_ARG(host); - GIT_UNUSED_ARG(port); - return git__throw(GIT_ENOTIMPLEMENTED, "Failed to get ODB backend. Feature not yet implemented"); -} - - -#endif /* HAVE_HIREDIS */ diff --git a/src/backends/sqlite.c b/src/backends/sqlite.c deleted file mode 100644 index 8626349ec..000000000 --- a/src/backends/sqlite.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, - * as published by the Free Software Foundation. - * - * In addition to the permissions in the GNU General Public License, - * the authors give you unlimited permission to link the compiled - * version of this file into combinations with other programs, - * and to distribute those combinations without any restriction - * coming from the use of this file. (The General Public License - * restrictions do apply in other respects; for example, they cover - * modification of the file, and distribution when not linked into - * a combined executable.) - * - * This file is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "common.h" -#include "git2/object.h" -#include "hash.h" -#include "odb.h" - -#include "git2/odb_backend.h" - -#ifdef GIT2_SQLITE_BACKEND - -#include <sqlite3.h> - -#define GIT2_TABLE_NAME "git2_odb" - -typedef struct { - git_odb_backend parent; - sqlite3 *db; - sqlite3_stmt *st_read; - sqlite3_stmt *st_write; - sqlite3_stmt *st_read_header; -} sqlite_backend; - -int sqlite_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) -{ - sqlite_backend *backend; - int error; - - assert(len_p && type_p && _backend && oid); - - backend = (sqlite_backend *)_backend; - error = GIT_ERROR; - - if (sqlite3_bind_text(backend->st_read_header, 1, (char *)oid->id, 20, SQLITE_TRANSIENT) == SQLITE_OK) { - if (sqlite3_step(backend->st_read_header) == SQLITE_ROW) { - *type_p = (git_otype)sqlite3_column_int(backend->st_read_header, 0); - *len_p = (size_t)sqlite3_column_int(backend->st_read_header, 1); - assert(sqlite3_step(backend->st_read_header) == SQLITE_DONE); - error = GIT_SUCCESS; - } else { - error = GIT_ENOTFOUND; - } - } - - sqlite3_reset(backend->st_read_header); - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "SQLite backend: Failed to read header"); -} - - -int sqlite_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, const git_oid *oid) -{ - sqlite_backend *backend; - int error; - - assert(data_p && len_p && type_p && _backend && oid); - - backend = (sqlite_backend *)_backend; - error = GIT_ERROR; - - if (sqlite3_bind_text(backend->st_read, 1, (char *)oid->id, 20, SQLITE_TRANSIENT) == SQLITE_OK) { - if (sqlite3_step(backend->st_read) == SQLITE_ROW) { - *type_p = (git_otype)sqlite3_column_int(backend->st_read, 0); - *len_p = (size_t)sqlite3_column_int(backend->st_read, 1); - *data_p = git__malloc(*len_p); - - if (*data_p == NULL) { - error = GIT_ENOMEM; - } else { - memcpy(*data_p, sqlite3_column_blob(backend->st_read, 2), *len_p); - error = GIT_SUCCESS; - } - - assert(sqlite3_step(backend->st_read) == SQLITE_DONE); - } else { - error = GIT_ENOTFOUND; - } - } - - sqlite3_reset(backend->st_read); - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "SQLite backend: Failed to read"); -} - -int sqlite_backend__read_prefix(git_oid *out_oid, void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend, - const git_oid *short_oid, unsigned int len) { - if (len >= GIT_OID_HEXSZ) { - /* Just match the full identifier */ - int error = sqlite_backend__read(data_p, len_p, type_p, _backend, short_oid); - if (error == GIT_SUCCESS) - git_oid_cpy(out_oid, short_oid); - - return error; - } else if (len < GIT_OID_HEXSZ) { - /* TODO */ - return git__throw(GIT_ENOTIMPLEMENTED, "Sqlite backend cannot search objects from short oid"); - } -} - -int sqlite_backend__exists(git_odb_backend *_backend, const git_oid *oid) -{ - sqlite_backend *backend; - int found; - - assert(_backend && oid); - - backend = (sqlite_backend *)_backend; - found = 0; - - if (sqlite3_bind_text(backend->st_read_header, 1, (char *)oid->id, 20, SQLITE_TRANSIENT) == SQLITE_OK) { - if (sqlite3_step(backend->st_read_header) == SQLITE_ROW) { - found = 1; - assert(sqlite3_step(backend->st_read_header) == SQLITE_DONE); - } - } - - sqlite3_reset(backend->st_read_header); - return found; -} - - -int sqlite_backend__write(git_oid *id, git_odb_backend *_backend, const void *data, size_t len, git_otype type) -{ - int error; - sqlite_backend *backend; - - assert(id && _backend && data); - - backend = (sqlite_backend *)_backend; - - if ((error = git_odb_hash(id, data, len, type)) < 0) - return git__rethrow(error, "SQLite backend: Failed to write"); - - error = SQLITE_ERROR; - - if (sqlite3_bind_text(backend->st_write, 1, (char *)id->id, 20, SQLITE_TRANSIENT) == SQLITE_OK && - sqlite3_bind_int(backend->st_write, 2, (int)type) == SQLITE_OK && - sqlite3_bind_int(backend->st_write, 3, len) == SQLITE_OK && - sqlite3_bind_blob(backend->st_write, 4, data, len, SQLITE_TRANSIENT) == SQLITE_OK) { - error = sqlite3_step(backend->st_write); - } - - sqlite3_reset(backend->st_write); - return (error == SQLITE_DONE) ? GIT_SUCCESS : git__throw(GIT_ERROR, "SQLite backend: Failed to write"); -} - - -void sqlite_backend__free(git_odb_backend *_backend) -{ - sqlite_backend *backend; - assert(_backend); - backend = (sqlite_backend *)_backend; - - sqlite3_finalize(backend->st_read); - sqlite3_finalize(backend->st_read_header); - sqlite3_finalize(backend->st_write); - sqlite3_close(backend->db); - - free(backend); -} - -static int create_table(sqlite3 *db) -{ - static const char *sql_creat = - "CREATE TABLE '" GIT2_TABLE_NAME "' (" - "'oid' CHARACTER(20) PRIMARY KEY NOT NULL," - "'type' INTEGER NOT NULL," - "'size' INTEGER NOT NULL," - "'data' BLOB);"; - - if (sqlite3_exec(db, sql_creat, NULL, NULL, NULL) != SQLITE_OK) - return git__throw(GIT_ERROR, "SQLite backend: Failed to create table"); - - return GIT_SUCCESS; -} - -static int init_db(sqlite3 *db) -{ - static const char *sql_check = - "SELECT name FROM sqlite_master WHERE type='table' AND name='" GIT2_TABLE_NAME "';"; - - sqlite3_stmt *st_check; - int error; - - if (sqlite3_prepare_v2(db, sql_check, -1, &st_check, NULL) != SQLITE_OK) - return git__throw(GIT_ERROR, "SQLite backend: Failed to initialize database"); - - switch (sqlite3_step(st_check)) { - case SQLITE_DONE: - /* the table was not found */ - error = create_table(db); - break; - - case SQLITE_ROW: - /* the table was found */ - error = GIT_SUCCESS; - break; - - default: - error = GIT_ERROR; - break; - } - - sqlite3_finalize(st_check); - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "SQLite backend: Failed to initialize database"); -} - -static int init_statements(sqlite_backend *backend) -{ - static const char *sql_read = - "SELECT type, size, data FROM '" GIT2_TABLE_NAME "' WHERE oid = ?;"; - - static const char *sql_read_header = - "SELECT type, size FROM '" GIT2_TABLE_NAME "' WHERE oid = ?;"; - - static const char *sql_write = - "INSERT OR IGNORE INTO '" GIT2_TABLE_NAME "' VALUES (?, ?, ?, ?);"; - - if (sqlite3_prepare_v2(backend->db, sql_read, -1, &backend->st_read, NULL) != SQLITE_OK) - return git__throw(GIT_ERROR, "SQLite backend: Failed to initialize statements"); - - if (sqlite3_prepare_v2(backend->db, sql_read_header, -1, &backend->st_read_header, NULL) != SQLITE_OK) - return git__throw(GIT_ERROR, "SQLite backend: Failed to initialize statements"); - - if (sqlite3_prepare_v2(backend->db, sql_write, -1, &backend->st_write, NULL) != SQLITE_OK) - return git__throw(GIT_ERROR, "SQLite backend: Failed to initialize statements"); - - return GIT_SUCCESS; -} - -int git_odb_backend_sqlite(git_odb_backend **backend_out, const char *sqlite_db) -{ - sqlite_backend *backend; - int error; - - backend = git__calloc(1, sizeof(sqlite_backend)); - if (backend == NULL) - return GIT_ENOMEM; - - if (sqlite3_open(sqlite_db, &backend->db) != SQLITE_OK) - goto cleanup; - - error = init_db(backend->db); - if (error < 0) - goto cleanup; - - error = init_statements(backend); - if (error < 0) - goto cleanup; - - backend->parent.read = &sqlite_backend__read; - backend->parent.read_prefix = &sqlite_backend__read_prefix; - backend->parent.read_header = &sqlite_backend__read_header; - backend->parent.write = &sqlite_backend__write; - backend->parent.exists = &sqlite_backend__exists; - backend->parent.free = &sqlite_backend__free; - - *backend_out = (git_odb_backend *)backend; - return GIT_SUCCESS; - -cleanup: - sqlite_backend__free((git_odb_backend *)backend); - return git__throw(GIT_ERROR, "SQLite backend: Failed to get ODB backend"); -} - -#else - -int git_odb_backend_sqlite(git_odb_backend **GIT_UNUSED(backend_out), const char *GIT_UNUSED(sqlite_db)) -{ - GIT_UNUSED_ARG(backend_out); - GIT_UNUSED_ARG(sqlite_db); - return git__throw(GIT_ENOTIMPLEMENTED, "SQLite backend: Failed to get ODB backend. Operation not yet implemented"); -} - -#endif /* HAVE_SQLITE3 */ diff --git a/src/blob.c b/src/blob.c index c95d018e2..ceb2c9c44 100644 --- a/src/blob.c +++ b/src/blob.c @@ -119,9 +119,9 @@ 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, sizeof(buffer)); + read_len = gitfo_read(fd, buffer, (size_t)(size < sizeof(buffer) ? size : sizeof(buffer))); else - read_len = gitfo_readlink(full_path, buffer, sizeof(buffer)); + read_len = gitfo_readlink(full_path, buffer, (size_t)size); if (read_len < 0) { if (!islnk) diff --git a/src/common.h b/src/common.h index f4f11fd2f..c83e00516 100644 --- a/src/common.h +++ b/src/common.h @@ -41,7 +41,6 @@ typedef SSIZE_T ssize_t; #else # include <unistd.h> -# include <arpa/inet.h> # ifdef GIT_THREADS # include <pthread.h> diff --git a/src/fileops.c b/src/fileops.c index 2a20617a5..58bc65c45 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -97,7 +97,7 @@ int gitfo_read(git_file fd, void *buf, size_t cnt) cnt -= r; b += r; } - return GIT_SUCCESS; + return (int)(b - (char *)buf); } int gitfo_write(git_file fd, void *buf, size_t cnt) @@ -193,7 +193,7 @@ int git_oid_ncmp_hex(unsigned int len, const unsigned char *a, const unsigned ch return memcmp(a, b, len); } -int gid_oid_ncmp(unsigned int len, git_oid *a, git_oid *b) +int git_oid_ncmp(unsigned int len, git_oid *a, git_oid *b) { return git_oid_ncmp_raw(len, a->id, b->id); } diff --git a/tests/t06-index.c b/tests/t06-index.c index 25adbf7c3..621deab2e 100644 --- a/tests/t06-index.c +++ b/tests/t06-index.c @@ -161,7 +161,6 @@ BEGIN_TEST(sort0, "sort the entires in an index") */ END_TEST - BEGIN_TEST(sort1, "sort the entires in an empty index") git_index *index; @@ -173,6 +172,46 @@ BEGIN_TEST(sort1, "sort the entires in an empty index") git_index_free(index); END_TEST +BEGIN_TEST(add0, "add a new file to the index") + git_index *index; + git_filebuf file; + git_repository *repo; + git_index_entry *entry; + git_oid id1; + + /* Intialize a new repository */ + must_pass(git_repository_init(&repo, TEMP_REPO_FOLDER "myrepo", 0)); + + /* Ensure we're the only guy in the room */ + must_pass(git_repository_index(&index, repo)); + 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_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)); + + /* Store the expected hash of the file/blob + * This has been generated by executing the following + * $ echo "hey there" | git hash-object --stdin + */ + must_pass(git_oid_mkstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); + + /* Add the new file to the index */ + must_pass(git_index_add(index, "test.txt", 0)); + + /* Wow... it worked! */ + must_pass(git_index_entrycount(index) == 1); + entry = git_index_get(index, 0); + + /* And the built-in hashing mechanism worked as expected */ + must_be_true(git_oid_cmp(&id1, &entry->oid) == 0); + + git_repository_free(repo); + rmdir_recurs(TEMP_REPO_FOLDER); +END_TEST + BEGIN_SUITE(index) ADD_TEST(read0); ADD_TEST(read1); @@ -185,4 +224,6 @@ BEGIN_SUITE(index) ADD_TEST(sort0); ADD_TEST(sort1); + + ADD_TEST(add0); END_SUITE diff --git a/tests/t11-sqlite.c b/tests/t11-sqlite.c deleted file mode 100644 index e9e08ac71..000000000 --- a/tests/t11-sqlite.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, - * as published by the Free Software Foundation. - * - * In addition to the permissions in the GNU General Public License, - * the authors give you unlimited permission to link the compiled - * version of this file into combinations with other programs, - * and to distribute those combinations without any restriction - * coming from the use of this file. (The General Public License - * restrictions do apply in other respects; for example, they cover - * modification of the file, and distribution when not linked into - * a combined executable.) - * - * This file is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#include "test_lib.h" -#include "odb.h" - -#ifdef GIT2_SQLITE_BACKEND -#include "t03-data.h" -#include "fileops.h" -#include "git2/odb_backend.h" - - -static int cmp_objects(git_odb_object *odb_obj, git_rawobj *raw) -{ - if (raw->type != git_odb_object_type(odb_obj)) - return -1; - - if (raw->len != git_odb_object_size(odb_obj)) - return -1; - - if ((raw->len > 0) && (memcmp(raw->data, git_odb_object_data(odb_obj), raw->len) != 0)) - return -1; - - return 0; -} - -static git_odb *open_sqlite_odb(void) -{ - git_odb *odb; - git_odb_backend *sqlite; - - if (git_odb_new(&odb) < GIT_SUCCESS) - return NULL; - - if (git_odb_backend_sqlite(&sqlite, ":memory:") < GIT_SUCCESS) - return NULL; - - if (git_odb_add_backend(odb, sqlite, 0) < GIT_SUCCESS) - return NULL; - - return odb; -} - -#define TEST_WRITE(PTR) {\ - git_odb *db; \ - git_oid id1, id2; \ - git_odb_object *obj; \ - db = open_sqlite_odb(); \ - must_be_true(db != NULL); \ - must_pass(git_oid_mkstr(&id1, PTR.id)); \ - must_pass(git_odb_write(&id2, db, PTR##_obj.data, PTR##_obj.len, PTR##_obj.type)); \ - must_be_true(git_oid_cmp(&id1, &id2) == 0); \ - must_pass(git_odb_read(&obj, db, &id1)); \ - must_pass(cmp_objects(obj, &PTR##_obj)); \ - git_odb_object_close(obj); \ - git_odb_close(db); \ -} - -BEGIN_TEST(sqlite0, "write a commit, read it back (sqlite backend)") - TEST_WRITE(commit); -END_TEST - -BEGIN_TEST(sqlite1, "write a tree, read it back (sqlite backend)") - TEST_WRITE(tree); -END_TEST - -BEGIN_TEST(sqlite2, "write a tag, read it back (sqlite backend)") - TEST_WRITE(tag); -END_TEST - -BEGIN_TEST(sqlite3, "write a zero-byte entry, read it back (sqlite backend)") - TEST_WRITE(zero); -END_TEST - -BEGIN_TEST(sqlite4, "write a one-byte entry, read it back (sqlite backend)") - TEST_WRITE(one); -END_TEST - -BEGIN_TEST(sqlite5, "write a two-byte entry, read it back (sqlite backend)") - TEST_WRITE(two); -END_TEST - -BEGIN_TEST(sqlite6, "write some bytes in an entry, read it back (sqlite backend)") - TEST_WRITE(some); -END_TEST - - -BEGIN_SUITE(sqlite) - ADD_TEST(sqlite0); - ADD_TEST(sqlite1); - ADD_TEST(sqlite2); - ADD_TEST(sqlite3); - ADD_TEST(sqlite4); - ADD_TEST(sqlite5); - ADD_TEST(sqlite6); -END_SUITE - -#else /* no sqlite builtin */ -BEGIN_SUITE(sqlite) - /* empty */ -END_SUITE -#endif - - - diff --git a/tests/t14-hiredis.c b/tests/t14-hiredis.c deleted file mode 100644 index c743f7d48..000000000 --- a/tests/t14-hiredis.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, - * as published by the Free Software Foundation. - * - * In addition to the permissions in the GNU General Public License, - * the authors give you unlimited permission to link the compiled - * version of this file into combinations with other programs, - * and to distribute those combinations without any restriction - * coming from the use of this file. (The General Public License - * restrictions do apply in other respects; for example, they cover - * modification of the file, and distribution when not linked into - * a combined executable.) - * - * This file is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#include "test_lib.h" -#include "odb.h" - -#ifdef GIT2_HIREDIS_BACKEND -#include "t03-data.h" -#include "fileops.h" -#include "git2/odb_backend.h" - - -static int cmp_objects(git_odb_object *odb_obj, git_rawobj *raw) -{ - if (raw->type != git_odb_object_type(odb_obj)) - return -1; - - if (raw->len != git_odb_object_size(odb_obj)) - return -1; - - if ((raw->len > 0) && (memcmp(raw->data, git_odb_object_data(odb_obj), raw->len) != 0)) - return -1; - - return 0; -} - -static git_odb *open_hiredis_odb(void) -{ - git_odb *odb; - git_odb_backend *hiredis; - - if (git_odb_new(&odb) < GIT_SUCCESS) - return NULL; - - if (git_odb_backend_hiredis(&hiredis, "127.0.0.1", 6379) < GIT_SUCCESS) - return NULL; - - if (git_odb_add_backend(odb, hiredis, 0) < GIT_SUCCESS) - return NULL; - - return odb; -} - -#define TEST_WRITE(PTR) {\ - git_odb *db; \ - git_oid id1, id2; \ - git_odb_object *obj; \ - db = open_hiredis_odb(); \ - must_be_true(db != NULL); \ - must_pass(git_oid_mkstr(&id1, PTR.id)); \ - must_pass(git_odb_write(&id2, db, PTR##_obj.data, PTR##_obj.len, PTR##_obj.type)); \ - must_be_true(git_oid_cmp(&id1, &id2) == 0); \ - must_pass(git_odb_read(&obj, db, &id1)); \ - must_pass(cmp_objects(obj, &PTR##_obj)); \ - git_odb_object_close(obj); \ - git_odb_close(db); \ -} - -BEGIN_TEST(hiredis0, "write a commit, read it back (hiredis backend)") - TEST_WRITE(commit); -END_TEST - -BEGIN_TEST(hiredis1, "write a tree, read it back (hiredis backend)") - TEST_WRITE(tree); -END_TEST - -BEGIN_TEST(hiredis2, "write a tag, read it back (hiredis backend)") - TEST_WRITE(tag); -END_TEST - -BEGIN_TEST(hiredis3, "write a zero-byte entry, read it back (hiredis backend)") - TEST_WRITE(zero); -END_TEST - -BEGIN_TEST(hiredis4, "write a one-byte entry, read it back (hiredis backend)") - TEST_WRITE(one); -END_TEST - -BEGIN_TEST(hiredis5, "write a two-byte entry, read it back (hiredis backend)") - TEST_WRITE(two); -END_TEST - -BEGIN_TEST(hiredis6, "write some bytes in an entry, read it back (hiredis backend)") - TEST_WRITE(some); -END_TEST - - -BEGIN_SUITE(hiredis) - ADD_TEST(hiredis0); - ADD_TEST(hiredis1); - ADD_TEST(hiredis2); - ADD_TEST(hiredis3); - ADD_TEST(hiredis4); - ADD_TEST(hiredis5); - ADD_TEST(hiredis6); -END_SUITE - -#else /* no hiredis builtin */ -BEGIN_SUITE(hiredis) - /* empty */ -END_SUITE -#endif diff --git a/tests/test_main.c b/tests/test_main.c index 0f5f16a26..3fd117d0b 100644 --- a/tests/test_main.c +++ b/tests/test_main.c @@ -40,8 +40,6 @@ DECLARE_SUITE(hashtable); DECLARE_SUITE(tag); DECLARE_SUITE(tree); DECLARE_SUITE(refs); -DECLARE_SUITE(sqlite); -DECLARE_SUITE(hiredis); DECLARE_SUITE(repository); DECLARE_SUITE(threads); DECLARE_SUITE(config); @@ -58,10 +56,8 @@ static libgit2_suite suite_methods[]= { SUITE_NAME(tag), SUITE_NAME(tree), SUITE_NAME(refs), - SUITE_NAME(sqlite), SUITE_NAME(repository), SUITE_NAME(threads), - SUITE_NAME(hiredis), SUITE_NAME(config), }; diff --git a/wscript b/wscript deleted file mode 100644 index fd877e468..000000000 --- a/wscript +++ /dev/null @@ -1,284 +0,0 @@ -from __future__ import with_statement -from waflib.Context import Context -from waflib.Build import BuildContext, CleanContext, \ - InstallContext, UninstallContext - -# Unix flags -CFLAGS_UNIX = ["-O2", "-Wall", "-Wextra", "-fPIC"] -CFLAGS_UNIX_DBG = ['-g', '-O0'] - -# Windows MSVC flags -CFLAGS_WIN32_COMMON = ['/TC', '/W4', '/WX', '/nologo', '/Zi'] -CFLAGS_WIN32_RELEASE = ['/O2', '/MD'] - -# Note: /RTC* cannot be used with optimization on. -CFLAGS_WIN32_DBG = ['/Od', '/RTC1', '/RTCc', '/DEBUG', '/MDd'] -CFLAGS_WIN32_L = ['/RELEASE'] # used for /both/ debug and release builds. - # sets the module's checksum in the header. -CFLAGS_WIN32_L_DBG = ['/DEBUG'] - -ALL_LIBS = ['crypto', 'pthread', 'sqlite3', 'hiredis'] - -def options(opt): - opt.load('compiler_c') - opt.add_option('--sha1', action='store', default='builtin', - help="Use the builtin SHA1 routines (builtin), the \ -PPC optimized version (ppc) or the SHA1 functions from OpenSSL (openssl)") - opt.add_option('--debug', action='store_true', default=False, - help='Compile with debug symbols') - opt.add_option('--msvc', action='store', default=None, - help='Force a specific MSVC++ version (7.1, 8.0, 9.0, 10.0), if more than one is installed') - opt.add_option('--arch', action='store', default='x86', - help='Select target architecture (ia64, x64, x86, x86_amd64, x86_ia64)') - opt.add_option('--with-sqlite', action='store_true', default=False, - dest='use_sqlite', help='Enable sqlite support') - opt.add_option('--with-hiredis', action='store_true', default=False, - dest='use_hiredis', help='Enable redis support using hiredis') - opt.add_option('--threadsafe', action='store_true', default=False, - help='Make libgit2 thread-safe (requires pthreads)') - -def configure(conf): - - # load the MSVC configuration flags - if conf.options.msvc: - conf.env['MSVC_VERSIONS'] = ['msvc ' + conf.options.msvc] - - conf.env['MSVC_TARGETS'] = [conf.options.arch] - - # default configuration for C programs - conf.load('compiler_c') - - dbg = conf.options.debug - - conf.env.CFLAGS += CFLAGS_UNIX + (CFLAGS_UNIX_DBG if dbg else []) - - if conf.env.DEST_OS == 'win32': - conf.env.PLATFORM = 'win32' - - if conf.env.CC_NAME == 'msvc': - conf.env.CFLAGS = CFLAGS_WIN32_COMMON + \ - (CFLAGS_WIN32_DBG if dbg else CFLAGS_WIN32_RELEASE) - conf.env.LINKFLAGS += CFLAGS_WIN32_L + \ - (CFLAGS_WIN32_L_DBG if dbg else []) - conf.env.DEFINES += ['WIN32', '_DEBUG', '_LIB'] - - else: - conf.env.PLATFORM = 'unix' - - if conf.env.DEST_OS == 'sunos': - conf.env.DEFINES += ['NO_VIZ'] - - if conf.options.threadsafe: - if conf.env.PLATFORM == 'unix': - conf.check_cc(lib='pthread', uselib_store='pthread') - conf.env.DEFINES += ['GIT_THREADS'] - - # check for sqlite3 - if conf.options.use_sqlite and conf.check_cc( - lib='sqlite3', uselib_store='sqlite3', install_path=None, mandatory=False): - conf.env.DEFINES += ['GIT2_SQLITE_BACKEND'] - - # check for hiredis - if conf.options.use_hiredis and conf.check_cc( - lib='hiredis', uselib_store='hiredis', install_path=None, mandatory=False): - conf.env.DEFINES += ['GIT2_HIREDIS_BACKEND'] - - - if conf.options.sha1 not in ['openssl', 'ppc', 'builtin']: - conf.fatal('Invalid SHA1 option') - - # check for libcrypto (openssl) if we are using its SHA1 functions - if conf.options.sha1 == 'openssl': - conf.check_cfg(package='libcrypto', args=['--cflags', '--libs'], uselib_store='crypto') - conf.env.DEFINES += ['OPENSSL_SHA1'] - - elif conf.options.sha1 == 'ppc': - conf.env.DEFINES += ['PPC_SHA1'] - - conf.env.sha1 = conf.options.sha1 - -def build(bld): - - # command '[build|clean|install|uninstall]-static' - if bld.variant == 'static': - build_library(bld, 'static') - - # command '[build|clean|install|uninstall]-shared' - elif bld.variant == 'shared': - build_library(bld, 'shared') - - # command '[build|clean]-tests' - elif bld.variant == 'test': - build_library(bld, 'objects') - build_test(bld) - - # command 'build|clean|install|uninstall': by default, run - # the same command for both the static and the shared lib - else: - from waflib import Options - Options.commands = [bld.cmd + '-shared', bld.cmd + '-static'] + Options.commands - -def get_libgit2_version(git2_h): - import re - line = None - - with open(git2_h) as f: - line = re.search(r'^#define LIBGIT2_VERSION "(\d+\.\d+\.\d+)"$', f.read(), re.MULTILINE) - - if line is None: - raise Exception("Failed to detect libgit2 version") - - return line.group(1) - - -def build_library(bld, build_type): - - BUILD = { - 'shared' : bld.shlib, - 'static' : bld.stlib, - 'objects' : bld.objects - } - - directory = bld.path - sources = directory.ant_glob('src/*.c') - - # Find the version of the library, from our header file - version = get_libgit2_version(directory.find_node("include/git2.h").abspath()) - - # Compile platform-dependant code - # E.g. src/unix/*.c - # src/win32/*.c - sources = sources + directory.ant_glob('src/%s/*.c' % bld.env.PLATFORM) - sources = sources + directory.ant_glob('src/backends/*.c') - sources = sources + directory.ant_glob('deps/zlib/*.c') - - # SHA1 methods source - if bld.env.sha1 == "ppc": - sources.append('src/ppc/sha1.c') - else: - sources.append('src/block-sha1/sha1.c') - #------------------------------ - # Build the main library - #------------------------------ - - # either as static or shared; - BUILD[build_type]( - source=sources, - target='git2', - includes=['src', 'include', 'deps/zlib'], - install_path='${LIBDIR}', - use=ALL_LIBS, - vnum=version, - ) - - # On Unix systems, build the Pkg-config entry file - if bld.env.PLATFORM == 'unix' and bld.is_install: - bld(rule="""sed -e 's#@prefix@#${PREFIX}#' -e 's#@libdir@#${LIBDIR}#' -e 's#@version@#%s#' < ${SRC} > ${TGT}""" % version, - source='libgit2.pc.in', - target='libgit2.pc', - install_path='${LIBDIR}/pkgconfig', - ) - - # Install headers - bld.install_files('${PREFIX}/include', directory.find_node('include/git2.h')) - bld.install_files('${PREFIX}/include/git2', directory.ant_glob('include/git2/*.h')) - - # On Unix systems, let them know about installation - if bld.env.PLATFORM == 'unix' and bld.cmd == 'install-shared': - bld.add_post_fun(call_ldconfig) - -def call_ldconfig(bld): - import distutils.spawn as s - ldconf = s.find_executable('ldconfig') - if ldconf: - bld.exec_command(ldconf) - -def build_test(bld): - directory = bld.path - resources_path = directory.find_node('tests/resources/').abspath().replace('\\', '/') - - sources = ['tests/test_lib.c', 'tests/test_helpers.c', 'tests/test_main.c'] - sources = sources + directory.ant_glob('tests/t??-*.c') - - bld.program( - source=sources, - target='libgit2_test', - includes=['src', 'tests', 'include'], - defines=['TEST_RESOURCES="%s"' % resources_path], - use=['git2'] + ALL_LIBS - ) - -class _test(BuildContext): - cmd = 'test' - fun = 'test' - -def test(bld): - from waflib import Options - Options.commands = ['build-test', 'run-test'] + Options.commands - -class _build_doc(Context): - cmd = 'doxygen' - fun = 'build_docs' - -def build_docs(ctx): - ctx.exec_command("doxygen api.doxygen") - ctx.exec_command("git stash") - ctx.exec_command("git checkout gh-pages") - ctx.exec_command("cp -Rf apidocs/html/* .") - ctx.exec_command("git add .") - ctx.exec_command("git commit -am 'generated docs'") - ctx.exec_command("git push origin gh-pages") - ctx.exec_command("git checkout master") - -class _run_test(Context): - cmd = 'run-test' - fun = 'run_test' - -def run_test(ctx): - import shutil, tempfile, sys - - failed = False - - test_path = 'build/test/libgit2_test' - if sys.platform == 'win32': - test_path += '.exe' - - test_folder = tempfile.mkdtemp() - test = ctx.path.find_node(test_path) - - if not test or ctx.exec_command(test.abspath(), cwd=test_folder) != 0: - failed = True - - shutil.rmtree(test_folder) - - if failed: - ctx.fatal('Test run failed') - - -CONTEXTS = { - 'build' : BuildContext, - 'clean' : CleanContext, - 'install' : InstallContext, - 'uninstall' : UninstallContext -} - -def build_command(command): - ctx, var = command.split('-') - class _gen_command(CONTEXTS[ctx]): - cmd = command - variant = var - -build_command('build-static') -build_command('build-shared') -build_command('build-test') - -build_command('clean-static') -build_command('clean-shared') -build_command('clean-test') - -build_command('install-static') -build_command('install-shared') - -build_command('uninstall-static') -build_command('uninstall-shared') - |
