mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-03 19:59:33 +00:00
Merge branch 'development' into vmg/dupe-odb-backends
Conflicts: src/odb.c
This commit is contained in:
commit
0edad3cc04
11
.mailmap
11
.mailmap
@ -5,3 +5,14 @@ Ben Straub <bs@github.com> Ben Straub <ben@straubnet.net>
|
||||
Ben Straub <bs@github.com> Ben Straub <bstraub@github.com>
|
||||
Carlos Martín Nieto <cmn@dwim.me> <carlos@cmartin.tk>
|
||||
Carlos Martín Nieto <cmn@dwim.me> <cmn@elego.de>
|
||||
nulltoken <emeric.fermas@gmail.com> <emeric.fermas@gmail.com>
|
||||
Scott J. Goldman <scottjg@github.com> <scottjgo@gmail.com>
|
||||
Martin Woodward <martin.woodward@microsoft.com> <martinwo@microsoft.com>
|
||||
Peter Drahoš <drahosp@gmail.com> <drahosp@gmail.com>
|
||||
Adam Roben <adam@github.com> <adam@roben.org>
|
||||
Adam Roben <adam@github.com> <adam@github.com>
|
||||
Xavier L. <xavier.l@afrosoft.tk> <xavier.l@afrosoft.ca>
|
||||
Xavier L. <xavier.l@afrosoft.tk> <xavier.l@afrosoft.tk>
|
||||
Sascha Cunz <sascha@babbelbox.org> <Sascha@BabbelBox.org>
|
||||
Authmillenon <authmillenon@googlemail.com> <martin@ucsmail.de>
|
||||
Authmillenon <authmillenon@googlemail.com> <authmillenon@googlemail.com>
|
||||
|
||||
11
README.md
11
README.md
@ -19,6 +19,7 @@ release its source code.
|
||||
* Archives: <http://librelist.com/browser/libgit2/>
|
||||
* Website: <http://libgit2.github.com>
|
||||
* API documentation: <http://libgit2.github.com/libgit2>
|
||||
* IRC: #libgit2 on irc.freenode.net.
|
||||
|
||||
What It Can Do
|
||||
==================================
|
||||
@ -155,15 +156,7 @@ we can add it to the list.
|
||||
How Can I Contribute?
|
||||
==================================
|
||||
|
||||
Fork libgit2/libgit2 on GitHub, add your improvement, push it to a branch
|
||||
in your fork named for the topic, send a pull request. If you change the
|
||||
API or make other large changes, make a note of it in docs/rel-notes/ in a
|
||||
file named after the next release.
|
||||
|
||||
You can also file bugs or feature requests under the libgit2 project on
|
||||
GitHub, or join us on the mailing list by sending an email to:
|
||||
|
||||
libgit2@librelist.com
|
||||
Check the [contribution guidelines](CONTRIBUTING.md).
|
||||
|
||||
|
||||
License
|
||||
|
||||
@ -201,14 +201,12 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
|
||||
unsigned int n);
|
||||
|
||||
/**
|
||||
* Create a new commit in the repository using `git_object`
|
||||
* instances as parameters.
|
||||
* Create new commit in the repository from a list of `git_object` pointers
|
||||
*
|
||||
* The message will not be cleaned up. This can be achieved
|
||||
* through `git_message_prettify()`.
|
||||
* The message will not be cleaned up automatically. You can do that with
|
||||
* the `git_message_prettify()` function.
|
||||
*
|
||||
* @param id Pointer where to store the OID of the
|
||||
* newly created commit
|
||||
* @param id Pointer in which to store the OID of the newly created commit
|
||||
*
|
||||
* @param repo Repository where to store the commit
|
||||
*
|
||||
@ -219,73 +217,69 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
|
||||
* make it point to this commit. If the reference doesn't
|
||||
* exist yet, it will be created.
|
||||
*
|
||||
* @param author Signature representing the author and the authory
|
||||
* time of this commit
|
||||
* @param author Signature with author and author time of commit
|
||||
*
|
||||
* @param committer Signature representing the committer and the
|
||||
* commit time of this commit
|
||||
* @param committer Signature with committer and * commit time of commit
|
||||
*
|
||||
* @param message_encoding The encoding for the message in the
|
||||
* commit, represented with a standard encoding name.
|
||||
* E.g. "UTF-8". If NULL, no encoding header is written and
|
||||
* UTF-8 is assumed.
|
||||
* commit, represented with a standard encoding name.
|
||||
* E.g. "UTF-8". If NULL, no encoding header is written and
|
||||
* UTF-8 is assumed.
|
||||
*
|
||||
* @param message Full message for this 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`.
|
||||
* 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 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`.
|
||||
* 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 or an error code
|
||||
* The created commit will be written to the Object Database and
|
||||
* the given reference will be updated to point to it
|
||||
*/
|
||||
GIT_EXTERN(int) git_commit_create(
|
||||
git_oid *id,
|
||||
git_repository *repo,
|
||||
const char *update_ref,
|
||||
const git_signature *author,
|
||||
const git_signature *committer,
|
||||
const char *message_encoding,
|
||||
const char *message,
|
||||
const git_tree *tree,
|
||||
int parent_count,
|
||||
const git_commit *parents[]);
|
||||
git_oid *id,
|
||||
git_repository *repo,
|
||||
const char *update_ref,
|
||||
const git_signature *author,
|
||||
const git_signature *committer,
|
||||
const char *message_encoding,
|
||||
const char *message,
|
||||
const git_tree *tree,
|
||||
int parent_count,
|
||||
const git_commit *parents[]);
|
||||
|
||||
/**
|
||||
* Create a new commit in the repository using a variable
|
||||
* argument list.
|
||||
* Create new commit in the repository using a variable argument list.
|
||||
*
|
||||
* The message will be cleaned up from excess whitespace
|
||||
* it will be made sure that the last line ends with a '\n'.
|
||||
* The message will be cleaned up from excess whitespace and it will be made
|
||||
* sure that the last line ends with a '\n'.
|
||||
*
|
||||
* The parents for the commit are specified as a variable
|
||||
* list of pointers to `const git_commit *`. Note that this
|
||||
* is a convenience method which may not be safe to export
|
||||
* for certain languages or compilers
|
||||
* The parents for the commit are specified as a variable list of pointers
|
||||
* to `const git_commit *`. 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
|
||||
* All other parameters remain the same at `git_commit_create()`.
|
||||
*
|
||||
* @see git_commit_create
|
||||
*/
|
||||
GIT_EXTERN(int) git_commit_create_v(
|
||||
git_oid *id,
|
||||
git_repository *repo,
|
||||
const char *update_ref,
|
||||
const git_signature *author,
|
||||
const git_signature *committer,
|
||||
const char *message_encoding,
|
||||
const char *message,
|
||||
const git_tree *tree,
|
||||
int parent_count,
|
||||
...);
|
||||
git_oid *id,
|
||||
git_repository *repo,
|
||||
const char *update_ref,
|
||||
const git_signature *author,
|
||||
const git_signature *committer,
|
||||
const char *message_encoding,
|
||||
const char *message,
|
||||
const git_tree *tree,
|
||||
int parent_count,
|
||||
...);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
@ -43,29 +43,6 @@ typedef struct {
|
||||
|
||||
typedef int (*git_config_foreach_cb)(const git_config_entry *, void *);
|
||||
|
||||
|
||||
/**
|
||||
* Generic backend that implements the interface to
|
||||
* access a configuration file
|
||||
*/
|
||||
struct git_config_backend {
|
||||
unsigned int version;
|
||||
struct git_config *cfg;
|
||||
|
||||
/* Open means open the file/database and parse if necessary */
|
||||
int (*open)(struct git_config_backend *, unsigned int level);
|
||||
int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry);
|
||||
int (*get_multivar)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload);
|
||||
int (*set)(struct git_config_backend *, const char *key, const char *value);
|
||||
int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
|
||||
int (*del)(struct git_config_backend *, const char *key);
|
||||
int (*foreach)(struct git_config_backend *, const char *, git_config_foreach_cb callback, void *payload);
|
||||
int (*refresh)(struct git_config_backend *);
|
||||
void (*free)(struct git_config_backend *);
|
||||
};
|
||||
#define GIT_CONFIG_BACKEND_VERSION 1
|
||||
#define GIT_CONFIG_BACKEND_INIT {GIT_CONFIG_BACKEND_VERSION}
|
||||
|
||||
typedef enum {
|
||||
GIT_CVAR_FALSE = 0,
|
||||
GIT_CVAR_TRUE = 1,
|
||||
@ -153,30 +130,6 @@ GIT_EXTERN(int) git_config_open_default(git_config **out);
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_new(git_config **out);
|
||||
|
||||
/**
|
||||
* Add a generic config file instance to an existing config
|
||||
*
|
||||
* Note that the configuration object will free the file
|
||||
* automatically.
|
||||
*
|
||||
* Further queries on this config object will access each
|
||||
* of the config file instances in order (instances with
|
||||
* a higher priority level will be accessed first).
|
||||
*
|
||||
* @param cfg the configuration to add the file to
|
||||
* @param file the configuration file (backend) to add
|
||||
* @param level the priority level of the backend
|
||||
* @param force if a config file already exists for the given
|
||||
* priority level, replace it
|
||||
* @return 0 on success, GIT_EEXISTS when adding more than one file
|
||||
* for a given priority level (and force_replace set to 0), or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_add_backend(
|
||||
git_config *cfg,
|
||||
git_config_backend *file,
|
||||
unsigned int level,
|
||||
int force);
|
||||
|
||||
/**
|
||||
* Add an on-disk config file instance to an existing config
|
||||
*
|
||||
@ -192,10 +145,9 @@ GIT_EXTERN(int) git_config_add_backend(
|
||||
* a higher priority level will be accessed first).
|
||||
*
|
||||
* @param cfg the configuration to add the file to
|
||||
* @param path path to the configuration file (backend) to add
|
||||
* @param path path to the configuration file to add
|
||||
* @param level the priority level of the backend
|
||||
* @param force if a config file already exists for the given
|
||||
* priority level, replace it
|
||||
* @param force replace config file at the given priority level
|
||||
* @return 0 on success, GIT_EEXISTS when adding more than one file
|
||||
* for a given priority level (and force_replace set to 0),
|
||||
* GIT_ENOTFOUND when the file doesn't exist or error code
|
||||
|
||||
@ -8,31 +8,11 @@
|
||||
#define _INCLUDE_git_indexer_h__
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "oid.h"
|
||||
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* This is passed as the first argument to the callback to allow the
|
||||
* user to see the progress.
|
||||
*/
|
||||
typedef struct git_transfer_progress {
|
||||
unsigned int total_objects;
|
||||
unsigned int indexed_objects;
|
||||
unsigned int received_objects;
|
||||
size_t received_bytes;
|
||||
} git_transfer_progress;
|
||||
|
||||
|
||||
/**
|
||||
* Type for progress callbacks during indexing. Return a value less than zero
|
||||
* to cancel the transfer.
|
||||
*
|
||||
* @param stats Structure containing information about the state of the transfer
|
||||
* @param payload Payload provided by caller
|
||||
*/
|
||||
typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload);
|
||||
|
||||
typedef struct git_indexer_stream git_indexer_stream;
|
||||
|
||||
/**
|
||||
|
||||
@ -10,8 +10,6 @@
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "oid.h"
|
||||
#include "odb_backend.h"
|
||||
#include "indexer.h"
|
||||
|
||||
/**
|
||||
* @file git2/odb.h
|
||||
@ -22,6 +20,11 @@
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Function type for callbacks from git_odb_foreach.
|
||||
*/
|
||||
typedef int (*git_odb_foreach_cb)(const git_oid *id, void *payload);
|
||||
|
||||
/**
|
||||
* Create a new object database with no backends.
|
||||
*
|
||||
@ -52,42 +55,6 @@ GIT_EXTERN(int) git_odb_new(git_odb **out);
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
|
||||
|
||||
/**
|
||||
* Add a custom backend to an existing Object DB
|
||||
*
|
||||
* The backends are checked in relative ordering, based on the
|
||||
* value of the `priority` parameter.
|
||||
*
|
||||
* Read <odb_backends.h> for more information.
|
||||
*
|
||||
* @param odb database to add the backend to
|
||||
* @param backend pointer to a git_odb_backend instance
|
||||
* @param priority Value for ordering the backends queue
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority);
|
||||
|
||||
/**
|
||||
* Add a custom backend to an existing Object DB; this
|
||||
* backend will work as an alternate.
|
||||
*
|
||||
* Alternate backends are always checked for objects *after*
|
||||
* all the main backends have been exhausted.
|
||||
*
|
||||
* The backends are checked in relative ordering, based on the
|
||||
* value of the `priority` parameter.
|
||||
*
|
||||
* Writing is disabled on alternate backends.
|
||||
*
|
||||
* Read <odb_backends.h> for more information.
|
||||
*
|
||||
* @param odb database to add the backend to
|
||||
* @param backend pointer to a git_odb_backend instance
|
||||
* @param priority Value for ordering the backends queue
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority);
|
||||
|
||||
/**
|
||||
* Add an on-disk alternate to an existing Object DB.
|
||||
*
|
||||
@ -406,6 +373,60 @@ GIT_EXTERN(size_t) git_odb_object_size(git_odb_object *object);
|
||||
*/
|
||||
GIT_EXTERN(git_otype) git_odb_object_type(git_odb_object *object);
|
||||
|
||||
/**
|
||||
* Add a custom backend to an existing Object DB
|
||||
*
|
||||
* The backends are checked in relative ordering, based on the
|
||||
* value of the `priority` parameter.
|
||||
*
|
||||
* Read <odb_backends.h> for more information.
|
||||
*
|
||||
* @param odb database to add the backend to
|
||||
* @param backend pointer to a git_odb_backend instance
|
||||
* @param priority Value for ordering the backends queue
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority);
|
||||
|
||||
/**
|
||||
* Add a custom backend to an existing Object DB; this
|
||||
* backend will work as an alternate.
|
||||
*
|
||||
* Alternate backends are always checked for objects *after*
|
||||
* all the main backends have been exhausted.
|
||||
*
|
||||
* The backends are checked in relative ordering, based on the
|
||||
* value of the `priority` parameter.
|
||||
*
|
||||
* Writing is disabled on alternate backends.
|
||||
*
|
||||
* Read <odb_backends.h> for more information.
|
||||
*
|
||||
* @param odb database to add the backend to
|
||||
* @param backend pointer to a git_odb_backend instance
|
||||
* @param priority Value for ordering the backends queue
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority);
|
||||
|
||||
/**
|
||||
* Get the number of ODB backend objects
|
||||
*
|
||||
* @param odb object database
|
||||
* @return number of backends in the ODB
|
||||
*/
|
||||
GIT_EXTERN(size_t) git_odb_num_backends(git_odb *odb);
|
||||
|
||||
/**
|
||||
* Lookup an ODB backend object by index
|
||||
*
|
||||
* @param out output pointer to ODB backend at pos
|
||||
* @param odb object database
|
||||
* @param pos index into object database backend list
|
||||
* @return 0 on success; GIT_ENOTFOUND if pos is invalid; other errors < 0
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
||||
@ -7,106 +7,24 @@
|
||||
#ifndef INCLUDE_git_odb_backend_h__
|
||||
#define INCLUDE_git_odb_backend_h__
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "oid.h"
|
||||
#include "indexer.h"
|
||||
#include "git2/common.h"
|
||||
#include "git2/types.h"
|
||||
|
||||
/**
|
||||
* @file git2/backend.h
|
||||
* @brief Git custom backend functions
|
||||
* @defgroup git_backend Git custom backend API
|
||||
* @defgroup git_odb Git object database routines
|
||||
* @ingroup Git
|
||||
* @{
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
struct git_odb_stream;
|
||||
struct git_odb_writepack;
|
||||
|
||||
/**
|
||||
* Function type for callbacks from git_odb_foreach.
|
||||
* Constructors for in-box ODB backends.
|
||||
*/
|
||||
typedef int (*git_odb_foreach_cb)(const git_oid *id, void *payload);
|
||||
|
||||
/**
|
||||
* An instance for a custom backend
|
||||
*/
|
||||
struct git_odb_backend {
|
||||
unsigned int version;
|
||||
git_odb *odb;
|
||||
|
||||
/* read and read_prefix each return to libgit2 a buffer which
|
||||
* will be freed later. The buffer should be allocated using
|
||||
* the function git_odb_backend_malloc to ensure that it can
|
||||
* be safely freed later. */
|
||||
int (* read)(
|
||||
void **, size_t *, git_otype *,
|
||||
struct git_odb_backend *,
|
||||
const git_oid *);
|
||||
|
||||
/* To find a unique object given a prefix
|
||||
* of its oid.
|
||||
* The oid given must be so that the
|
||||
* remaining (GIT_OID_HEXSZ - len)*4 bits
|
||||
* are 0s.
|
||||
*/
|
||||
int (* read_prefix)(
|
||||
git_oid *,
|
||||
void **, size_t *, git_otype *,
|
||||
struct git_odb_backend *,
|
||||
const git_oid *,
|
||||
size_t);
|
||||
|
||||
int (* read_header)(
|
||||
size_t *, git_otype *,
|
||||
struct git_odb_backend *,
|
||||
const git_oid *);
|
||||
|
||||
/* The writer may assume that the object
|
||||
* has already been hashed and is passed
|
||||
* in the first parameter.
|
||||
*/
|
||||
int (* write)(
|
||||
git_oid *,
|
||||
struct git_odb_backend *,
|
||||
const void *,
|
||||
size_t,
|
||||
git_otype);
|
||||
|
||||
int (* writestream)(
|
||||
struct git_odb_stream **,
|
||||
struct git_odb_backend *,
|
||||
size_t,
|
||||
git_otype);
|
||||
|
||||
int (* readstream)(
|
||||
struct git_odb_stream **,
|
||||
struct git_odb_backend *,
|
||||
const git_oid *);
|
||||
|
||||
int (* exists)(
|
||||
struct git_odb_backend *,
|
||||
const git_oid *);
|
||||
|
||||
int (* refresh)(struct git_odb_backend *);
|
||||
|
||||
int (* foreach)(
|
||||
struct git_odb_backend *,
|
||||
git_odb_foreach_cb cb,
|
||||
void *payload);
|
||||
|
||||
int (* writepack)(
|
||||
struct git_odb_writepack **,
|
||||
struct git_odb_backend *,
|
||||
git_transfer_progress_callback progress_cb,
|
||||
void *progress_payload);
|
||||
|
||||
void (* free)(struct git_odb_backend *);
|
||||
};
|
||||
|
||||
#define GIT_ODB_BACKEND_VERSION 1
|
||||
#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION}
|
||||
GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_dir);
|
||||
GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **out, const char *objects_dir, int compression_level, int do_fsync);
|
||||
GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **out, const char *index_file);
|
||||
|
||||
/** Streaming mode */
|
||||
enum {
|
||||
@ -117,33 +35,24 @@ enum {
|
||||
|
||||
/** A stream to read/write from a backend */
|
||||
struct git_odb_stream {
|
||||
struct git_odb_backend *backend;
|
||||
git_odb_backend *backend;
|
||||
unsigned int mode;
|
||||
|
||||
int (*read)(struct git_odb_stream *stream, char *buffer, size_t len);
|
||||
int (*write)(struct git_odb_stream *stream, const char *buffer, size_t len);
|
||||
int (*finalize_write)(git_oid *oid_p, struct git_odb_stream *stream);
|
||||
void (*free)(struct git_odb_stream *stream);
|
||||
int (*read)(git_odb_stream *stream, char *buffer, size_t len);
|
||||
int (*write)(git_odb_stream *stream, const char *buffer, size_t len);
|
||||
int (*finalize_write)(git_oid *oid_p, git_odb_stream *stream);
|
||||
void (*free)(git_odb_stream *stream);
|
||||
};
|
||||
|
||||
/** A stream to write a pack file to the ODB */
|
||||
struct git_odb_writepack {
|
||||
struct git_odb_backend *backend;
|
||||
git_odb_backend *backend;
|
||||
|
||||
int (*add)(struct git_odb_writepack *writepack, const void *data, size_t size, git_transfer_progress *stats);
|
||||
int (*commit)(struct git_odb_writepack *writepack, git_transfer_progress *stats);
|
||||
void (*free)(struct git_odb_writepack *writepack);
|
||||
int (*add)(git_odb_writepack *writepack, const void *data, size_t size, git_transfer_progress *stats);
|
||||
int (*commit)(git_odb_writepack *writepack, git_transfer_progress *stats);
|
||||
void (*free)(git_odb_writepack *writepack);
|
||||
};
|
||||
|
||||
GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len);
|
||||
|
||||
/**
|
||||
* Constructors for in-box ODB backends.
|
||||
*/
|
||||
GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_dir);
|
||||
GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **out, const char *objects_dir, int compression_level, int do_fsync);
|
||||
GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **out, const char *index_file);
|
||||
|
||||
GIT_END_DECL
|
||||
|
||||
#endif
|
||||
|
||||
@ -21,27 +21,6 @@
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Create a new reference. Either an oid or a symbolic target must be
|
||||
* specified.
|
||||
*
|
||||
* @param refdb the reference database to associate with this reference
|
||||
* @param name the reference name
|
||||
* @param oid the object id for a direct reference
|
||||
* @param symbolic the target for a symbolic reference
|
||||
* @return the created git_reference or NULL on error
|
||||
*/
|
||||
GIT_EXTERN(git_reference *) git_reference__alloc(
|
||||
git_refdb *refdb,
|
||||
const char *name,
|
||||
const git_oid *oid,
|
||||
const git_oid *peel);
|
||||
|
||||
GIT_EXTERN(git_reference *) git_reference__alloc_symbolic(
|
||||
git_refdb *refdb,
|
||||
const char *name,
|
||||
const char *target);
|
||||
|
||||
/**
|
||||
* Create a new reference database with no backends.
|
||||
*
|
||||
@ -83,20 +62,6 @@ GIT_EXTERN(int) git_refdb_compress(git_refdb *refdb);
|
||||
*/
|
||||
GIT_EXTERN(void) git_refdb_free(git_refdb *refdb);
|
||||
|
||||
/**
|
||||
* Sets the custom backend to an existing reference DB
|
||||
*
|
||||
* Read <refdb_backends.h> for more information.
|
||||
*
|
||||
* @param refdb database to add the backend to
|
||||
* @param backend pointer to a git_refdb_backend instance
|
||||
* @param priority Value for ordering the backends queue
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_refdb_set_backend(
|
||||
git_refdb *refdb,
|
||||
git_refdb_backend *backend);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
|
||||
@ -184,7 +184,8 @@ GIT_EXTERN(const git_refspec *) git_remote_pushspec(const git_remote *remote);
|
||||
* starts up a specific binary which can only do the one or the other.
|
||||
*
|
||||
* @param remote the remote to connect to
|
||||
* @param direction whether you want to receive or send data
|
||||
* @param direction GIT_DIRECTION_FETCH if you want to fetch or
|
||||
* GIT_DIRECTION_PUSH if you want to push
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction);
|
||||
|
||||
@ -400,21 +400,6 @@ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_config(git_config **out, git_repository *repo);
|
||||
|
||||
/**
|
||||
* Set the configuration file for this repository
|
||||
*
|
||||
* This configuration file will be used for all configuration
|
||||
* queries involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the config file;
|
||||
* the user must still free the config after setting it
|
||||
* to the repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param config A Config object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *config);
|
||||
|
||||
/**
|
||||
* Get the Object Database for this repository.
|
||||
*
|
||||
@ -431,21 +416,6 @@ GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *con
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_odb(git_odb **out, git_repository *repo);
|
||||
|
||||
/**
|
||||
* Set the Object Database for this repository
|
||||
*
|
||||
* The ODB will be used for all object-related operations
|
||||
* involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the ODB; the user
|
||||
* must still free the ODB object after setting it to the
|
||||
* repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param odb An ODB object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb);
|
||||
|
||||
/**
|
||||
* Get the Reference Database Backend for this repository.
|
||||
*
|
||||
@ -462,23 +432,6 @@ GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb);
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_refdb(git_refdb **out, git_repository *repo);
|
||||
|
||||
/**
|
||||
* Set the Reference Database Backend for this repository
|
||||
*
|
||||
* The refdb will be used for all reference related operations
|
||||
* involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the refdb; the user
|
||||
* must still free the refdb object after setting it to the
|
||||
* repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param refdb An refdb object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_refdb(
|
||||
git_repository *repo,
|
||||
git_refdb *refdb);
|
||||
|
||||
/**
|
||||
* Get the Index file for this repository.
|
||||
*
|
||||
@ -495,21 +448,6 @@ GIT_EXTERN(void) git_repository_set_refdb(
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo);
|
||||
|
||||
/**
|
||||
* Set the index file for this repository
|
||||
*
|
||||
* This index will be used for all index-related operations
|
||||
* involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the index file;
|
||||
* the user must still free the index after setting it
|
||||
* to the repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param index An index object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
|
||||
|
||||
/**
|
||||
* Retrieve git's prepared message
|
||||
*
|
||||
|
||||
45
include/git2/sys/commit.h
Normal file
45
include/git2/sys/commit.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#ifndef INCLUDE_sys_git_commit_h__
|
||||
#define INCLUDE_sys_git_commit_h__
|
||||
|
||||
#include "git2/common.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/oid.h"
|
||||
|
||||
/**
|
||||
* @file git2/sys/commit.h
|
||||
* @brief Low-level Git commit creation
|
||||
* @defgroup git_backend Git custom backend APIs
|
||||
* @ingroup Git
|
||||
* @{
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Create new commit in the repository from a list of `git_oid` values
|
||||
*
|
||||
* See documentation for `git_commit_create()` for information about the
|
||||
* parameters, as the meaning is identical excepting that `tree` and
|
||||
* `parents` now take `git_oid`. This is a dangerous API in that the
|
||||
* `parents` list of `git_oid`s in not checked for validity.
|
||||
*/
|
||||
GIT_EXTERN(int) git_commit_create_from_oids(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *update_ref,
|
||||
const git_signature *author,
|
||||
const git_signature *committer,
|
||||
const char *message_encoding,
|
||||
const char *message,
|
||||
const git_oid *tree,
|
||||
int parent_count,
|
||||
const git_oid *parents[]);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
71
include/git2/sys/config.h
Normal file
71
include/git2/sys/config.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#ifndef INCLUDE_sys_git_config_backend_h__
|
||||
#define INCLUDE_sys_git_config_backend_h__
|
||||
|
||||
#include "git2/common.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/config.h"
|
||||
|
||||
/**
|
||||
* @file git2/sys/config.h
|
||||
* @brief Git config backend routines
|
||||
* @defgroup git_backend Git custom backend APIs
|
||||
* @ingroup Git
|
||||
* @{
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Generic backend that implements the interface to
|
||||
* access a configuration file
|
||||
*/
|
||||
struct git_config_backend {
|
||||
unsigned int version;
|
||||
struct git_config *cfg;
|
||||
|
||||
/* Open means open the file/database and parse if necessary */
|
||||
int (*open)(struct git_config_backend *, unsigned int level);
|
||||
int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry);
|
||||
int (*get_multivar)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload);
|
||||
int (*set)(struct git_config_backend *, const char *key, const char *value);
|
||||
int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value);
|
||||
int (*del)(struct git_config_backend *, const char *key);
|
||||
int (*foreach)(struct git_config_backend *, const char *, git_config_foreach_cb callback, void *payload);
|
||||
int (*refresh)(struct git_config_backend *);
|
||||
void (*free)(struct git_config_backend *);
|
||||
};
|
||||
#define GIT_CONFIG_BACKEND_VERSION 1
|
||||
#define GIT_CONFIG_BACKEND_INIT {GIT_CONFIG_BACKEND_VERSION}
|
||||
|
||||
/**
|
||||
* Add a generic config file instance to an existing config
|
||||
*
|
||||
* Note that the configuration object will free the file
|
||||
* automatically.
|
||||
*
|
||||
* Further queries on this config object will access each
|
||||
* of the config file instances in order (instances with
|
||||
* a higher priority level will be accessed first).
|
||||
*
|
||||
* @param cfg the configuration to add the file to
|
||||
* @param file the configuration file (backend) to add
|
||||
* @param level the priority level of the backend
|
||||
* @param force if a config file already exists for the given
|
||||
* priority level, replace it
|
||||
* @return 0 on success, GIT_EEXISTS when adding more than one file
|
||||
* for a given priority level (and force_replace set to 0), or error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_config_add_backend(
|
||||
git_config *cfg,
|
||||
git_config_backend *file,
|
||||
unsigned int level,
|
||||
int force);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
86
include/git2/sys/odb_backend.h
Normal file
86
include/git2/sys/odb_backend.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#ifndef INCLUDE_sys_git_odb_backend_h__
|
||||
#define INCLUDE_sys_git_odb_backend_h__
|
||||
|
||||
#include "git2/common.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/oid.h"
|
||||
#include "git2/odb.h"
|
||||
|
||||
/**
|
||||
* @file git2/sys/backend.h
|
||||
* @brief Git custom backend implementors functions
|
||||
* @defgroup git_backend Git custom backend APIs
|
||||
* @ingroup Git
|
||||
* @{
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* An instance for a custom backend
|
||||
*/
|
||||
struct git_odb_backend {
|
||||
unsigned int version;
|
||||
git_odb *odb;
|
||||
|
||||
/* read and read_prefix each return to libgit2 a buffer which
|
||||
* will be freed later. The buffer should be allocated using
|
||||
* the function git_odb_backend_malloc to ensure that it can
|
||||
* be safely freed later. */
|
||||
int (* read)(
|
||||
void **, size_t *, git_otype *, git_odb_backend *, const git_oid *);
|
||||
|
||||
/* To find a unique object given a prefix
|
||||
* of its oid.
|
||||
* The oid given must be so that the
|
||||
* remaining (GIT_OID_HEXSZ - len)*4 bits
|
||||
* are 0s.
|
||||
*/
|
||||
int (* read_prefix)(
|
||||
git_oid *, void **, size_t *, git_otype *,
|
||||
git_odb_backend *, const git_oid *, size_t);
|
||||
|
||||
int (* read_header)(
|
||||
size_t *, git_otype *, git_odb_backend *, const git_oid *);
|
||||
|
||||
/* The writer may assume that the object
|
||||
* has already been hashed and is passed
|
||||
* in the first parameter.
|
||||
*/
|
||||
int (* write)(
|
||||
git_oid *, git_odb_backend *, const void *, size_t, git_otype);
|
||||
|
||||
int (* writestream)(
|
||||
git_odb_stream **, git_odb_backend *, size_t, git_otype);
|
||||
|
||||
int (* readstream)(
|
||||
git_odb_stream **, git_odb_backend *, const git_oid *);
|
||||
|
||||
int (* exists)(
|
||||
git_odb_backend *, const git_oid *);
|
||||
|
||||
int (* refresh)(git_odb_backend *);
|
||||
|
||||
int (* foreach)(
|
||||
git_odb_backend *, git_odb_foreach_cb cb, void *payload);
|
||||
|
||||
int (* writepack)(
|
||||
git_odb_writepack **, git_odb_backend *,
|
||||
git_transfer_progress_callback progress_cb, void *progress_payload);
|
||||
|
||||
void (* free)(git_odb_backend *);
|
||||
};
|
||||
|
||||
#define GIT_ODB_BACKEND_VERSION 1
|
||||
#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION}
|
||||
|
||||
GIT_EXTERN(void *) git_odb_backend_malloc(git_odb_backend *backend, size_t len);
|
||||
|
||||
GIT_END_DECL
|
||||
|
||||
#endif
|
||||
@ -4,12 +4,12 @@
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#ifndef INCLUDE_git_refdb_backend_h__
|
||||
#define INCLUDE_git_refdb_backend_h__
|
||||
#ifndef INCLUDE_sys_git_refdb_backend_h__
|
||||
#define INCLUDE_sys_git_refdb_backend_h__
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "oid.h"
|
||||
#include "git2/common.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/oid.h"
|
||||
|
||||
/**
|
||||
* @file git2/refdb_backend.h
|
||||
@ -30,7 +30,7 @@ struct git_refdb_backend {
|
||||
*/
|
||||
int (*exists)(
|
||||
int *exists,
|
||||
struct git_refdb_backend *backend,
|
||||
git_refdb_backend *backend,
|
||||
const char *ref_name);
|
||||
|
||||
/**
|
||||
@ -39,7 +39,7 @@ struct git_refdb_backend {
|
||||
*/
|
||||
int (*lookup)(
|
||||
git_reference **out,
|
||||
struct git_refdb_backend *backend,
|
||||
git_refdb_backend *backend,
|
||||
const char *ref_name);
|
||||
|
||||
/**
|
||||
@ -47,7 +47,7 @@ struct git_refdb_backend {
|
||||
* provide this function.
|
||||
*/
|
||||
int (*foreach)(
|
||||
struct git_refdb_backend *backend,
|
||||
git_refdb_backend *backend,
|
||||
unsigned int list_flags,
|
||||
git_reference_foreach_cb callback,
|
||||
void *payload);
|
||||
@ -59,7 +59,7 @@ struct git_refdb_backend {
|
||||
* against the glob.
|
||||
*/
|
||||
int (*foreach_glob)(
|
||||
struct git_refdb_backend *backend,
|
||||
git_refdb_backend *backend,
|
||||
const char *glob,
|
||||
unsigned int list_flags,
|
||||
git_reference_foreach_cb callback,
|
||||
@ -69,13 +69,13 @@ struct git_refdb_backend {
|
||||
* Writes the given reference to the refdb. A refdb implementation
|
||||
* must provide this function.
|
||||
*/
|
||||
int (*write)(struct git_refdb_backend *backend, const git_reference *ref);
|
||||
int (*write)(git_refdb_backend *backend, const git_reference *ref);
|
||||
|
||||
/**
|
||||
* Deletes the given reference from the refdb. A refdb implementation
|
||||
* must provide this function.
|
||||
*/
|
||||
int (*delete)(struct git_refdb_backend *backend, const git_reference *ref);
|
||||
int (*delete)(git_refdb_backend *backend, const git_reference *ref);
|
||||
|
||||
/**
|
||||
* Suggests that the given refdb compress or optimize its references.
|
||||
@ -84,25 +84,46 @@ struct git_refdb_backend {
|
||||
* implementation may provide this function; if it is not provided,
|
||||
* nothing will be done.
|
||||
*/
|
||||
int (*compress)(struct git_refdb_backend *backend);
|
||||
int (*compress)(git_refdb_backend *backend);
|
||||
|
||||
/**
|
||||
* Frees any resources held by the refdb. A refdb implementation may
|
||||
* provide this function; if it is not provided, nothing will be done.
|
||||
*/
|
||||
void (*free)(struct git_refdb_backend *backend);
|
||||
void (*free)(git_refdb_backend *backend);
|
||||
};
|
||||
|
||||
#define GIT_ODB_BACKEND_VERSION 1
|
||||
#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION}
|
||||
|
||||
/**
|
||||
* Constructors for default refdb backends.
|
||||
* Constructors for default filesystem-based refdb backend
|
||||
*
|
||||
* Under normal usage, this is called for you when the repository is
|
||||
* opened / created, but you can use this to explicitly construct a
|
||||
* filesystem refdb backend for a repository.
|
||||
*
|
||||
* @param backend_out Output pointer to the git_refdb_backend object
|
||||
* @param repo Git repository to access
|
||||
* @return 0 on success, <0 error code on failure
|
||||
*/
|
||||
GIT_EXTERN(int) git_refdb_backend_fs(
|
||||
struct git_refdb_backend **backend_out,
|
||||
git_repository *repo,
|
||||
git_refdb *refdb);
|
||||
git_refdb_backend **backend_out,
|
||||
git_repository *repo);
|
||||
|
||||
/**
|
||||
* Sets the custom backend to an existing reference DB
|
||||
*
|
||||
* The `git_refdb` will take ownership of the `git_refdb_backend` so you
|
||||
* should NOT free it after calling this function.
|
||||
*
|
||||
* @param refdb database to add the backend to
|
||||
* @param backend pointer to a git_refdb_backend instance
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_refdb_set_backend(
|
||||
git_refdb *refdb,
|
||||
git_refdb_backend *backend);
|
||||
|
||||
GIT_END_DECL
|
||||
|
||||
38
include/git2/sys/refs.h
Normal file
38
include/git2/sys/refs.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#ifndef INCLUDE_sys_git_refdb_h__
|
||||
#define INCLUDE_sys_git_refdb_h__
|
||||
|
||||
#include "git2/common.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/oid.h"
|
||||
|
||||
/**
|
||||
* Create a new direct reference from an OID.
|
||||
*
|
||||
* @param name the reference name
|
||||
* @param oid the object id for a direct reference
|
||||
* @param symbolic the target for a symbolic reference
|
||||
* @return the created git_reference or NULL on error
|
||||
*/
|
||||
GIT_EXTERN(git_reference *) git_reference__alloc(
|
||||
const char *name,
|
||||
const git_oid *oid,
|
||||
const git_oid *peel);
|
||||
|
||||
/**
|
||||
* Create a new symbolic reference.
|
||||
*
|
||||
* @param name the reference name
|
||||
* @param symbolic the target for a symbolic reference
|
||||
* @return the created git_reference or NULL on error
|
||||
*/
|
||||
GIT_EXTERN(git_reference *) git_reference__alloc_symbolic(
|
||||
const char *name,
|
||||
const char *target);
|
||||
|
||||
#endif
|
||||
92
include/git2/sys/repository.h
Normal file
92
include/git2/sys/repository.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#ifndef INCLUDE_sys_git_repository_h__
|
||||
#define INCLUDE_sys_git_repository_h__
|
||||
|
||||
/**
|
||||
* @file git2/sys/repository.h
|
||||
* @brief Git repository custom implementation routines
|
||||
* @defgroup git_backend Git custom backend APIs
|
||||
* @ingroup Git
|
||||
* @{
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Create a new repository with neither backends nor config object
|
||||
*
|
||||
* Note that this is only useful if you wish to associate the repository
|
||||
* with a non-filesystem-backed object database and config store.
|
||||
*
|
||||
* @param out The blank repository
|
||||
* @return 0 on success, or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_new(git_repository **out);
|
||||
|
||||
/**
|
||||
* Set the configuration file for this repository
|
||||
*
|
||||
* This configuration file will be used for all configuration
|
||||
* queries involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the config file;
|
||||
* the user must still free the config after setting it
|
||||
* to the repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param config A Config object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *config);
|
||||
|
||||
/**
|
||||
* Set the Object Database for this repository
|
||||
*
|
||||
* The ODB will be used for all object-related operations
|
||||
* involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the ODB; the user
|
||||
* must still free the ODB object after setting it to the
|
||||
* repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param odb An ODB object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb);
|
||||
|
||||
/**
|
||||
* Set the Reference Database Backend for this repository
|
||||
*
|
||||
* The refdb will be used for all reference related operations
|
||||
* involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the refdb; the user
|
||||
* must still free the refdb object after setting it to the
|
||||
* repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param refdb An refdb object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_refdb(git_repository *repo, git_refdb *refdb);
|
||||
|
||||
/**
|
||||
* Set the index file for this repository
|
||||
*
|
||||
* This index will be used for all index-related operations
|
||||
* involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the index file;
|
||||
* the user must still free the index after setting it
|
||||
* to the repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param index An index object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
@ -196,6 +196,26 @@ typedef struct git_push git_push;
|
||||
typedef struct git_remote_head git_remote_head;
|
||||
typedef struct git_remote_callbacks git_remote_callbacks;
|
||||
|
||||
/**
|
||||
* This is passed as the first argument to the callback to allow the
|
||||
* user to see the progress.
|
||||
*/
|
||||
typedef struct git_transfer_progress {
|
||||
unsigned int total_objects;
|
||||
unsigned int indexed_objects;
|
||||
unsigned int received_objects;
|
||||
size_t received_bytes;
|
||||
} git_transfer_progress;
|
||||
|
||||
/**
|
||||
* Type for progress callbacks during indexing. Return a value less than zero
|
||||
* to cancel the transfer.
|
||||
*
|
||||
* @param stats Structure containing information about the state of the transfer
|
||||
* @param payload Payload provided by caller
|
||||
*/
|
||||
typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "git2/common.h"
|
||||
#include "git2/object.h"
|
||||
#include "git2/repository.h"
|
||||
#include "git2/odb_backend.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "blob.h"
|
||||
|
||||
@ -377,7 +377,7 @@ int git_branch_remote_name(char *buffer, size_t buffer_len, git_repository *repo
|
||||
if (buffer)
|
||||
git_buf_copy_cstr(buffer, buffer_len, &buf);
|
||||
|
||||
ret = git_buf_len(&buf) + 1;
|
||||
ret = (int)git_buf_len(&buf) + 1;
|
||||
git_buf_free(&buf);
|
||||
|
||||
return ret;
|
||||
|
||||
87
src/commit.c
87
src/commit.c
@ -9,6 +9,7 @@
|
||||
#include "git2/object.h"
|
||||
#include "git2/repository.h"
|
||||
#include "git2/signature.h"
|
||||
#include "git2/sys/commit.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "odb.h"
|
||||
@ -44,16 +45,16 @@ void git_commit__free(git_commit *commit)
|
||||
}
|
||||
|
||||
int git_commit_create_v(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *update_ref,
|
||||
const git_signature *author,
|
||||
const git_signature *committer,
|
||||
const char *message_encoding,
|
||||
const char *message,
|
||||
const git_tree *tree,
|
||||
int parent_count,
|
||||
...)
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *update_ref,
|
||||
const git_signature *author,
|
||||
const git_signature *committer,
|
||||
const char *message_encoding,
|
||||
const char *message,
|
||||
const git_tree *tree,
|
||||
int parent_count,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
int i, res;
|
||||
@ -76,30 +77,29 @@ int git_commit_create_v(
|
||||
return res;
|
||||
}
|
||||
|
||||
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_encoding,
|
||||
const char *message,
|
||||
const git_tree *tree,
|
||||
int parent_count,
|
||||
const git_commit *parents[])
|
||||
int git_commit_create_from_oids(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *update_ref,
|
||||
const git_signature *author,
|
||||
const git_signature *committer,
|
||||
const char *message_encoding,
|
||||
const char *message,
|
||||
const git_oid *tree,
|
||||
int parent_count,
|
||||
const git_oid *parents[])
|
||||
{
|
||||
git_buf commit = GIT_BUF_INIT;
|
||||
int i;
|
||||
git_odb *odb;
|
||||
|
||||
assert(oid && repo && tree && parent_count >= 0);
|
||||
assert(git_object_owner((const git_object *)tree) == repo);
|
||||
|
||||
git_oid__writebuf(&commit, "tree ", git_object_id((const git_object *)tree));
|
||||
git_oid__writebuf(&commit, "tree ", tree);
|
||||
|
||||
for (i = 0; i < parent_count; ++i) {
|
||||
assert(git_object_owner((const git_object *)parents[i]) == repo);
|
||||
git_oid__writebuf(&commit, "parent ", git_object_id((const git_object *)parents[i]));
|
||||
}
|
||||
for (i = 0; i < parent_count; ++i)
|
||||
git_oid__writebuf(&commit, "parent ", parents[i]);
|
||||
|
||||
git_signature__writebuf(&commit, "author ", author);
|
||||
git_signature__writebuf(&commit, "committer ", committer);
|
||||
@ -131,6 +131,41 @@ on_error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
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_encoding,
|
||||
const char *message,
|
||||
const git_tree *tree,
|
||||
int parent_count,
|
||||
const git_commit *parents[])
|
||||
{
|
||||
int retval, i;
|
||||
const git_oid **parent_oids;
|
||||
|
||||
assert(parent_count >= 0);
|
||||
|
||||
parent_oids = git__malloc(parent_count * sizeof(git_oid *));
|
||||
GITERR_CHECK_ALLOC(parent_oids);
|
||||
|
||||
for (i = 0; i < parent_count; ++i) {
|
||||
assert(git_object_owner((const git_object *)parents[i]) == repo);
|
||||
parent_oids[i] = git_object_id((const git_object *)parents[i]);
|
||||
}
|
||||
|
||||
retval = git_commit_create_from_oids(
|
||||
oid, repo, update_ref, author, committer,
|
||||
message_encoding, message,
|
||||
git_object_id((const git_object *)tree), parent_count, parent_oids);
|
||||
|
||||
git__free((void *)parent_oids);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len)
|
||||
{
|
||||
const char *buffer = data;
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include "fileops.h"
|
||||
#include "config.h"
|
||||
#include "git2/config.h"
|
||||
#include "git2/sys/config.h"
|
||||
#include "vector.h"
|
||||
#include "buf_text.h"
|
||||
#include "config_file.h"
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "buffer.h"
|
||||
#include "buf_text.h"
|
||||
#include "git2/config.h"
|
||||
#include "git2/sys/config.h"
|
||||
#include "git2/types.h"
|
||||
#include "strmap.h"
|
||||
|
||||
|
||||
@ -1345,7 +1345,7 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
|
||||
static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
|
||||
{
|
||||
unsigned int i;
|
||||
struct index_header header;
|
||||
struct index_header header = { 0 };
|
||||
git_oid checksum_calculated, checksum_expected;
|
||||
|
||||
#define seek_forward(_increase) { \
|
||||
|
||||
595
src/iterator.c
595
src/iterator.c
@ -26,8 +26,6 @@
|
||||
(GIT_ITERATOR_IGNORE_CASE | GIT_ITERATOR_DONT_IGNORE_CASE)
|
||||
|
||||
#define ITERATOR_BASE_INIT(P,NAME_LC,NAME_UC,REPO) do { \
|
||||
(P) = git__calloc(1, sizeof(NAME_LC ## _iterator)); \
|
||||
GITERR_CHECK_ALLOC(P); \
|
||||
(P)->base.type = GIT_ITERATOR_TYPE_ ## NAME_UC; \
|
||||
(P)->base.cb = &(P)->cb; \
|
||||
ITERATOR_SET_CB(P,NAME_LC); \
|
||||
@ -148,7 +146,8 @@ int git_iterator_for_nothing(
|
||||
const char *start,
|
||||
const char *end)
|
||||
{
|
||||
empty_iterator *i;
|
||||
empty_iterator *i = git__calloc(1, sizeof(empty_iterator));
|
||||
GITERR_CHECK_ALLOC(i);
|
||||
|
||||
#define empty_iterator__current empty_iterator__noop
|
||||
#define empty_iterator__advance empty_iterator__noop
|
||||
@ -581,6 +580,9 @@ int git_iterator_for_tree(
|
||||
if ((error = git_object_dup((git_object **)&tree, (git_object *)tree)) < 0)
|
||||
return error;
|
||||
|
||||
ti = git__calloc(1, sizeof(tree_iterator));
|
||||
GITERR_CHECK_ALLOC(ti);
|
||||
|
||||
ITERATOR_BASE_INIT(ti, tree, TREE, git_tree_owner(tree));
|
||||
|
||||
if ((error = iterator__update_ignore_case((git_iterator *)ti, flags)) < 0)
|
||||
@ -810,7 +812,8 @@ int git_iterator_for_index(
|
||||
const char *start,
|
||||
const char *end)
|
||||
{
|
||||
index_iterator *ii;
|
||||
index_iterator *ii = git__calloc(1, sizeof(index_iterator));
|
||||
GITERR_CHECK_ALLOC(ii);
|
||||
|
||||
ITERATOR_BASE_INIT(ii, index, INDEX, git_index_owner(index));
|
||||
|
||||
@ -833,237 +836,221 @@ int git_iterator_for_index(
|
||||
}
|
||||
|
||||
|
||||
#define WORKDIR_MAX_DEPTH 100
|
||||
|
||||
typedef struct workdir_iterator_frame workdir_iterator_frame;
|
||||
struct workdir_iterator_frame {
|
||||
workdir_iterator_frame *next;
|
||||
typedef struct fs_iterator_frame fs_iterator_frame;
|
||||
struct fs_iterator_frame {
|
||||
fs_iterator_frame *next;
|
||||
git_vector entries;
|
||||
size_t index;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
typedef struct fs_iterator fs_iterator;
|
||||
struct fs_iterator {
|
||||
git_iterator base;
|
||||
git_iterator_callbacks cb;
|
||||
workdir_iterator_frame *stack;
|
||||
git_ignores ignores;
|
||||
fs_iterator_frame *stack;
|
||||
git_index_entry entry;
|
||||
git_buf path;
|
||||
size_t root_len;
|
||||
int is_ignored;
|
||||
int depth;
|
||||
} workdir_iterator;
|
||||
|
||||
GIT_INLINE(bool) path_is_dotgit(const git_path_with_stat *ps)
|
||||
int (*enter_dir_cb)(fs_iterator *self);
|
||||
int (*leave_dir_cb)(fs_iterator *self);
|
||||
int (*update_entry_cb)(fs_iterator *self);
|
||||
};
|
||||
|
||||
#define FS_MAX_DEPTH 100
|
||||
|
||||
static fs_iterator_frame *fs_iterator__alloc_frame(fs_iterator *fi)
|
||||
{
|
||||
if (!ps)
|
||||
return false;
|
||||
else {
|
||||
const char *path = ps->path;
|
||||
size_t len = ps->path_len;
|
||||
|
||||
if (len < 4)
|
||||
return false;
|
||||
if (path[len - 1] == '/')
|
||||
len--;
|
||||
if (tolower(path[len - 1]) != 't' ||
|
||||
tolower(path[len - 2]) != 'i' ||
|
||||
tolower(path[len - 3]) != 'g' ||
|
||||
tolower(path[len - 4]) != '.')
|
||||
return false;
|
||||
return (len == 4 || path[len - 5] == '/');
|
||||
}
|
||||
}
|
||||
|
||||
static workdir_iterator_frame *workdir_iterator__alloc_frame(
|
||||
workdir_iterator *wi)
|
||||
{
|
||||
workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame));
|
||||
fs_iterator_frame *ff = git__calloc(1, sizeof(fs_iterator_frame));
|
||||
git_vector_cmp entry_compare = CASESELECT(
|
||||
iterator__ignore_case(wi),
|
||||
iterator__ignore_case(fi),
|
||||
git_path_with_stat_cmp_icase, git_path_with_stat_cmp);
|
||||
|
||||
if (wf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (git_vector_init(&wf->entries, 0, entry_compare) != 0) {
|
||||
git__free(wf);
|
||||
return NULL;
|
||||
if (ff && git_vector_init(&ff->entries, 0, entry_compare) < 0) {
|
||||
git__free(ff);
|
||||
ff = NULL;
|
||||
}
|
||||
|
||||
return wf;
|
||||
return ff;
|
||||
}
|
||||
|
||||
static void workdir_iterator__free_frame(workdir_iterator_frame *wf)
|
||||
static void fs_iterator__free_frame(fs_iterator_frame *ff)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t i;
|
||||
git_path_with_stat *path;
|
||||
|
||||
git_vector_foreach(&wf->entries, i, path)
|
||||
git_vector_foreach(&ff->entries, i, path)
|
||||
git__free(path);
|
||||
git_vector_free(&wf->entries);
|
||||
git__free(wf);
|
||||
git_vector_free(&ff->entries);
|
||||
git__free(ff);
|
||||
}
|
||||
|
||||
static int workdir_iterator__update_entry(workdir_iterator *wi);
|
||||
|
||||
static int workdir_iterator__entry_cmp(const void *i, const void *item)
|
||||
static void fs_iterator__pop_frame(
|
||||
fs_iterator *fi, fs_iterator_frame *ff, bool pop_last)
|
||||
{
|
||||
const workdir_iterator *wi = (const workdir_iterator *)i;
|
||||
const git_path_with_stat *ps = item;
|
||||
return wi->base.prefixcomp(wi->base.start, ps->path);
|
||||
}
|
||||
if (fi && fi->stack == ff) {
|
||||
if (!ff->next && !pop_last) {
|
||||
memset(&fi->entry, 0, sizeof(fi->entry));
|
||||
return;
|
||||
}
|
||||
|
||||
static void workdir_iterator__seek_frame_start(
|
||||
workdir_iterator *wi, workdir_iterator_frame *wf)
|
||||
{
|
||||
if (!wf)
|
||||
return;
|
||||
if (fi->leave_dir_cb)
|
||||
(void)fi->leave_dir_cb(fi);
|
||||
|
||||
if (wi->base.start)
|
||||
git_vector_bsearch2(
|
||||
&wf->index, &wf->entries, workdir_iterator__entry_cmp, wi);
|
||||
else
|
||||
wf->index = 0;
|
||||
|
||||
if (path_is_dotgit(git_vector_get(&wf->entries, wf->index)))
|
||||
wf->index++;
|
||||
}
|
||||
|
||||
static int workdir_iterator__expand_dir(workdir_iterator *wi)
|
||||
{
|
||||
int error;
|
||||
workdir_iterator_frame *wf;
|
||||
|
||||
wf = workdir_iterator__alloc_frame(wi);
|
||||
GITERR_CHECK_ALLOC(wf);
|
||||
|
||||
error = git_path_dirload_with_stat(
|
||||
wi->path.ptr, wi->root_len, iterator__ignore_case(wi),
|
||||
wi->base.start, wi->base.end, &wf->entries);
|
||||
|
||||
if (error < 0 || wf->entries.length == 0) {
|
||||
workdir_iterator__free_frame(wf);
|
||||
return GIT_ENOTFOUND;
|
||||
fi->stack = ff->next;
|
||||
fi->depth--;
|
||||
}
|
||||
|
||||
if (++(wi->depth) > WORKDIR_MAX_DEPTH) {
|
||||
fs_iterator__free_frame(ff);
|
||||
}
|
||||
|
||||
static int fs_iterator__update_entry(fs_iterator *fi);
|
||||
|
||||
static int fs_iterator__entry_cmp(const void *i, const void *item)
|
||||
{
|
||||
const fs_iterator *fi = (const fs_iterator *)i;
|
||||
const git_path_with_stat *ps = item;
|
||||
return fi->base.prefixcomp(fi->base.start, ps->path);
|
||||
}
|
||||
|
||||
static void fs_iterator__seek_frame_start(
|
||||
fs_iterator *fi, fs_iterator_frame *ff)
|
||||
{
|
||||
if (!ff)
|
||||
return;
|
||||
|
||||
if (fi->base.start)
|
||||
git_vector_bsearch2(
|
||||
&ff->index, &ff->entries, fs_iterator__entry_cmp, fi);
|
||||
else
|
||||
ff->index = 0;
|
||||
}
|
||||
|
||||
static int fs_iterator__expand_dir(fs_iterator *fi)
|
||||
{
|
||||
int error;
|
||||
fs_iterator_frame *ff;
|
||||
|
||||
if (fi->depth > FS_MAX_DEPTH) {
|
||||
giterr_set(GITERR_REPOSITORY,
|
||||
"Working directory is too deep (%d)", wi->depth);
|
||||
workdir_iterator__free_frame(wf);
|
||||
"Directory nesting is too deep (%d)", fi->depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
workdir_iterator__seek_frame_start(wi, wf);
|
||||
ff = fs_iterator__alloc_frame(fi);
|
||||
GITERR_CHECK_ALLOC(ff);
|
||||
|
||||
/* only push new ignores if this is not top level directory */
|
||||
if (wi->stack != NULL) {
|
||||
ssize_t slash_pos = git_buf_rfind_next(&wi->path, '/');
|
||||
(void)git_ignore__push_dir(&wi->ignores, &wi->path.ptr[slash_pos + 1]);
|
||||
error = git_path_dirload_with_stat(
|
||||
fi->path.ptr, fi->root_len, iterator__ignore_case(fi),
|
||||
fi->base.start, fi->base.end, &ff->entries);
|
||||
|
||||
if (error < 0 || ff->entries.length == 0) {
|
||||
fs_iterator__free_frame(ff);
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
wf->next = wi->stack;
|
||||
wi->stack = wf;
|
||||
fs_iterator__seek_frame_start(fi, ff);
|
||||
|
||||
return workdir_iterator__update_entry(wi);
|
||||
ff->next = fi->stack;
|
||||
fi->stack = ff;
|
||||
fi->depth++;
|
||||
|
||||
if (fi->enter_dir_cb && (error = fi->enter_dir_cb(fi)) < 0)
|
||||
return error;
|
||||
|
||||
return fs_iterator__update_entry(fi);
|
||||
}
|
||||
|
||||
static int workdir_iterator__current(
|
||||
static int fs_iterator__current(
|
||||
const git_index_entry **entry, git_iterator *self)
|
||||
{
|
||||
workdir_iterator *wi = (workdir_iterator *)self;
|
||||
fs_iterator *fi = (fs_iterator *)self;
|
||||
if (entry)
|
||||
*entry = (wi->entry.path == NULL) ? NULL : &wi->entry;
|
||||
*entry = (fi->entry.path == NULL) ? NULL : &fi->entry;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int workdir_iterator__at_end(git_iterator *self)
|
||||
static int fs_iterator__at_end(git_iterator *self)
|
||||
{
|
||||
return (((workdir_iterator *)self)->entry.path == NULL);
|
||||
return (((fs_iterator *)self)->entry.path == NULL);
|
||||
}
|
||||
|
||||
static int workdir_iterator__advance_into(
|
||||
static int fs_iterator__advance_into(
|
||||
const git_index_entry **entry, git_iterator *iter)
|
||||
{
|
||||
int error = 0;
|
||||
workdir_iterator *wi = (workdir_iterator *)iter;
|
||||
fs_iterator *fi = (fs_iterator *)iter;
|
||||
|
||||
iterator__clear_entry(entry);
|
||||
|
||||
/* workdir iterator will allow you to explicitly advance into a
|
||||
* commit/submodule (as well as a tree) to avoid some cases where an
|
||||
* entry is mislabeled as a submodule in the working directory
|
||||
/* Allow you to explicitly advance into a commit/submodule (as well as a
|
||||
* tree) to avoid cases where an entry is mislabeled as a submodule in
|
||||
* the working directory. The fs iterator will never have COMMMIT
|
||||
* entries on it's own, but a wrapper might add them.
|
||||
*/
|
||||
if (wi->entry.path != NULL &&
|
||||
(wi->entry.mode == GIT_FILEMODE_TREE ||
|
||||
wi->entry.mode == GIT_FILEMODE_COMMIT))
|
||||
if (fi->entry.path != NULL &&
|
||||
(fi->entry.mode == GIT_FILEMODE_TREE ||
|
||||
fi->entry.mode == GIT_FILEMODE_COMMIT))
|
||||
/* returns GIT_ENOTFOUND if the directory is empty */
|
||||
error = workdir_iterator__expand_dir(wi);
|
||||
error = fs_iterator__expand_dir(fi);
|
||||
|
||||
if (!error && entry)
|
||||
error = workdir_iterator__current(entry, iter);
|
||||
error = fs_iterator__current(entry, iter);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int workdir_iterator__advance(
|
||||
static int fs_iterator__advance_over(
|
||||
const git_index_entry **entry, git_iterator *self)
|
||||
{
|
||||
int error = 0;
|
||||
workdir_iterator *wi = (workdir_iterator *)self;
|
||||
workdir_iterator_frame *wf;
|
||||
fs_iterator *fi = (fs_iterator *)self;
|
||||
fs_iterator_frame *ff;
|
||||
git_path_with_stat *next;
|
||||
|
||||
/* given include_trees & autoexpand, we might have to go into a tree */
|
||||
if (iterator__do_autoexpand(wi) &&
|
||||
wi->entry.path != NULL &&
|
||||
wi->entry.mode == GIT_FILEMODE_TREE)
|
||||
{
|
||||
error = workdir_iterator__advance_into(entry, self);
|
||||
|
||||
/* continue silently past empty directories if autoexpanding */
|
||||
if (error != GIT_ENOTFOUND)
|
||||
return error;
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
}
|
||||
|
||||
if (entry != NULL)
|
||||
*entry = NULL;
|
||||
|
||||
while (wi->entry.path != NULL) {
|
||||
wf = wi->stack;
|
||||
next = git_vector_get(&wf->entries, ++wf->index);
|
||||
while (fi->entry.path != NULL) {
|
||||
ff = fi->stack;
|
||||
next = git_vector_get(&ff->entries, ++ff->index);
|
||||
|
||||
if (next != NULL) {
|
||||
/* match git's behavior of ignoring anything named ".git" */
|
||||
if (path_is_dotgit(next))
|
||||
continue;
|
||||
/* else found a good entry */
|
||||
if (next != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
/* pop stack if anything is left to pop */
|
||||
if (!wf->next) {
|
||||
memset(&wi->entry, 0, sizeof(wi->entry));
|
||||
return 0;
|
||||
}
|
||||
|
||||
wi->stack = wf->next;
|
||||
wi->depth--;
|
||||
workdir_iterator__free_frame(wf);
|
||||
git_ignore__pop_dir(&wi->ignores);
|
||||
fs_iterator__pop_frame(fi, ff, false);
|
||||
}
|
||||
|
||||
error = workdir_iterator__update_entry(wi);
|
||||
error = fs_iterator__update_entry(fi);
|
||||
|
||||
if (!error && entry != NULL)
|
||||
error = workdir_iterator__current(entry, self);
|
||||
error = fs_iterator__current(entry, self);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int workdir_iterator__seek(git_iterator *self, const char *prefix)
|
||||
static int fs_iterator__advance(
|
||||
const git_index_entry **entry, git_iterator *self)
|
||||
{
|
||||
fs_iterator *fi = (fs_iterator *)self;
|
||||
|
||||
/* given include_trees & autoexpand, we might have to go into a tree */
|
||||
if (iterator__do_autoexpand(fi) &&
|
||||
fi->entry.path != NULL &&
|
||||
fi->entry.mode == GIT_FILEMODE_TREE)
|
||||
{
|
||||
int error = fs_iterator__advance_into(entry, self);
|
||||
if (error != GIT_ENOTFOUND)
|
||||
return error;
|
||||
/* continue silently past empty directories if autoexpanding */
|
||||
giterr_clear();
|
||||
}
|
||||
|
||||
return fs_iterator__advance_over(entry, self);
|
||||
}
|
||||
|
||||
static int fs_iterator__seek(git_iterator *self, const char *prefix)
|
||||
{
|
||||
GIT_UNUSED(self);
|
||||
GIT_UNUSED(prefix);
|
||||
@ -1073,107 +1060,192 @@ static int workdir_iterator__seek(git_iterator *self, const char *prefix)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int workdir_iterator__reset(
|
||||
static int fs_iterator__reset(
|
||||
git_iterator *self, const char *start, const char *end)
|
||||
{
|
||||
workdir_iterator *wi = (workdir_iterator *)self;
|
||||
fs_iterator *fi = (fs_iterator *)self;
|
||||
|
||||
while (wi->stack != NULL && wi->stack->next != NULL) {
|
||||
workdir_iterator_frame *wf = wi->stack;
|
||||
wi->stack = wf->next;
|
||||
workdir_iterator__free_frame(wf);
|
||||
git_ignore__pop_dir(&wi->ignores);
|
||||
}
|
||||
wi->depth = 0;
|
||||
while (fi->stack != NULL && fi->stack->next != NULL)
|
||||
fs_iterator__pop_frame(fi, fi->stack, false);
|
||||
fi->depth = 0;
|
||||
|
||||
if (iterator__reset_range(self, start, end) < 0)
|
||||
return -1;
|
||||
|
||||
workdir_iterator__seek_frame_start(wi, wi->stack);
|
||||
fs_iterator__seek_frame_start(fi, fi->stack);
|
||||
|
||||
return workdir_iterator__update_entry(wi);
|
||||
return fs_iterator__update_entry(fi);
|
||||
}
|
||||
|
||||
static void fs_iterator__free(git_iterator *self)
|
||||
{
|
||||
fs_iterator *fi = (fs_iterator *)self;
|
||||
|
||||
while (fi->stack != NULL)
|
||||
fs_iterator__pop_frame(fi, fi->stack, true);
|
||||
|
||||
git_buf_free(&fi->path);
|
||||
}
|
||||
|
||||
static int fs_iterator__update_entry(fs_iterator *fi)
|
||||
{
|
||||
git_path_with_stat *ps =
|
||||
git_vector_get(&fi->stack->entries, fi->stack->index);
|
||||
|
||||
git_buf_truncate(&fi->path, fi->root_len);
|
||||
memset(&fi->entry, 0, sizeof(fi->entry));
|
||||
|
||||
if (!ps)
|
||||
return 0;
|
||||
if (git_buf_put(&fi->path, ps->path, ps->path_len) < 0)
|
||||
return -1;
|
||||
if (iterator__past_end(fi, fi->path.ptr + fi->root_len))
|
||||
return 0;
|
||||
|
||||
fi->entry.path = ps->path;
|
||||
git_index_entry__init_from_stat(&fi->entry, &ps->st);
|
||||
|
||||
/* need different mode here to keep directories during iteration */
|
||||
fi->entry.mode = git_futils_canonical_mode(ps->st.st_mode);
|
||||
|
||||
/* allow wrapper to check/update the entry (can force skip) */
|
||||
if (fi->update_entry_cb &&
|
||||
fi->update_entry_cb(fi) == GIT_ENOTFOUND)
|
||||
return fs_iterator__advance_over(NULL, (git_iterator *)fi);
|
||||
|
||||
/* if this is a tree and trees aren't included, then skip */
|
||||
if (fi->entry.mode == GIT_FILEMODE_TREE && !iterator__include_trees(fi))
|
||||
return git_iterator_advance(NULL, (git_iterator *)fi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fs_iterator__initialize(
|
||||
git_iterator **out, fs_iterator *fi, const char *root)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (git_buf_sets(&fi->path, root) < 0 || git_path_to_dir(&fi->path) < 0) {
|
||||
git__free(fi);
|
||||
return -1;
|
||||
}
|
||||
fi->root_len = fi->path.size;
|
||||
|
||||
if ((error = fs_iterator__expand_dir(fi)) == GIT_ENOTFOUND) {
|
||||
giterr_clear();
|
||||
error = 0;
|
||||
}
|
||||
if (error) {
|
||||
git_iterator_free((git_iterator *)fi);
|
||||
fi = NULL;
|
||||
}
|
||||
|
||||
*out = (git_iterator *)fi;
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_iterator_for_filesystem(
|
||||
git_iterator **out,
|
||||
const char *root,
|
||||
git_iterator_flag_t flags,
|
||||
const char *start,
|
||||
const char *end)
|
||||
{
|
||||
fs_iterator *fi = git__calloc(1, sizeof(fs_iterator));
|
||||
GITERR_CHECK_ALLOC(fi);
|
||||
|
||||
ITERATOR_BASE_INIT(fi, fs, FS, NULL);
|
||||
|
||||
if ((flags & GIT_ITERATOR_IGNORE_CASE) != 0)
|
||||
fi->base.flags |= GIT_ITERATOR_IGNORE_CASE;
|
||||
|
||||
return fs_iterator__initialize(out, fi, root);
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
fs_iterator fi;
|
||||
git_ignores ignores;
|
||||
int is_ignored;
|
||||
} workdir_iterator;
|
||||
|
||||
GIT_INLINE(bool) workdir_path_is_dotgit(const git_buf *path)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (!path || (len = path->size) < 4)
|
||||
return false;
|
||||
|
||||
if (path->ptr[len - 1] == '/')
|
||||
len--;
|
||||
|
||||
if (tolower(path->ptr[len - 1]) != 't' ||
|
||||
tolower(path->ptr[len - 2]) != 'i' ||
|
||||
tolower(path->ptr[len - 3]) != 'g' ||
|
||||
tolower(path->ptr[len - 4]) != '.')
|
||||
return false;
|
||||
|
||||
return (len == 4 || path->ptr[len - 5] == '/');
|
||||
}
|
||||
|
||||
static int workdir_iterator__enter_dir(fs_iterator *fi)
|
||||
{
|
||||
/* only push new ignores if this is not top level directory */
|
||||
if (fi->stack->next != NULL) {
|
||||
workdir_iterator *wi = (workdir_iterator *)fi;
|
||||
ssize_t slash_pos = git_buf_rfind_next(&fi->path, '/');
|
||||
|
||||
(void)git_ignore__push_dir(&wi->ignores, &fi->path.ptr[slash_pos + 1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int workdir_iterator__leave_dir(fs_iterator *fi)
|
||||
{
|
||||
workdir_iterator *wi = (workdir_iterator *)fi;
|
||||
git_ignore__pop_dir(&wi->ignores);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int workdir_iterator__update_entry(fs_iterator *fi)
|
||||
{
|
||||
int error = 0;
|
||||
workdir_iterator *wi = (workdir_iterator *)fi;
|
||||
|
||||
/* skip over .git entries */
|
||||
if (workdir_path_is_dotgit(&fi->path))
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
/* reset is_ignored since we haven't checked yet */
|
||||
wi->is_ignored = -1;
|
||||
|
||||
/* check if apparent tree entries are actually submodules */
|
||||
if (fi->entry.mode != GIT_FILEMODE_TREE)
|
||||
return 0;
|
||||
|
||||
error = git_submodule_lookup(NULL, fi->base.repo, fi->entry.path);
|
||||
if (error < 0)
|
||||
giterr_clear();
|
||||
|
||||
/* mark submodule (or any dir with .git) as GITLINK and remove slash */
|
||||
if (!error || error == GIT_EEXISTS) {
|
||||
fi->entry.mode = S_IFGITLINK;
|
||||
fi->entry.path[strlen(fi->entry.path) - 1] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void workdir_iterator__free(git_iterator *self)
|
||||
{
|
||||
workdir_iterator *wi = (workdir_iterator *)self;
|
||||
|
||||
while (wi->stack != NULL) {
|
||||
workdir_iterator_frame *wf = wi->stack;
|
||||
wi->stack = wf->next;
|
||||
workdir_iterator__free_frame(wf);
|
||||
}
|
||||
|
||||
fs_iterator__free(self);
|
||||
git_ignore__free(&wi->ignores);
|
||||
git_buf_free(&wi->path);
|
||||
}
|
||||
|
||||
static int workdir_iterator__update_entry(workdir_iterator *wi)
|
||||
{
|
||||
int error = 0;
|
||||
git_path_with_stat *ps =
|
||||
git_vector_get(&wi->stack->entries, wi->stack->index);
|
||||
|
||||
git_buf_truncate(&wi->path, wi->root_len);
|
||||
memset(&wi->entry, 0, sizeof(wi->entry));
|
||||
|
||||
if (!ps)
|
||||
return 0;
|
||||
|
||||
/* skip over .git entries */
|
||||
if (path_is_dotgit(ps))
|
||||
return workdir_iterator__advance(NULL, (git_iterator *)wi);
|
||||
|
||||
if (git_buf_put(&wi->path, ps->path, ps->path_len) < 0)
|
||||
return -1;
|
||||
|
||||
if (iterator__past_end(wi, wi->path.ptr + wi->root_len))
|
||||
return 0;
|
||||
|
||||
wi->entry.path = ps->path;
|
||||
|
||||
wi->is_ignored = -1;
|
||||
|
||||
git_index_entry__init_from_stat(&wi->entry, &ps->st);
|
||||
|
||||
/* need different mode here to keep directories during iteration */
|
||||
wi->entry.mode = git_futils_canonical_mode(ps->st.st_mode);
|
||||
|
||||
/* if this is a file type we don't handle, treat as ignored */
|
||||
if (wi->entry.mode == 0) {
|
||||
wi->is_ignored = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if this isn't a tree, then we're done */
|
||||
if (wi->entry.mode != GIT_FILEMODE_TREE)
|
||||
return 0;
|
||||
|
||||
/* detect submodules */
|
||||
error = git_submodule_lookup(NULL, wi->base.repo, wi->entry.path);
|
||||
if (error == GIT_ENOTFOUND)
|
||||
giterr_clear();
|
||||
|
||||
if (error == GIT_EEXISTS) /* if contains .git, treat as untracked submod */
|
||||
error = 0;
|
||||
|
||||
/* if submodule, mark as GITLINK and remove trailing slash */
|
||||
if (!error) {
|
||||
size_t len = strlen(wi->entry.path);
|
||||
assert(wi->entry.path[len - 1] == '/');
|
||||
wi->entry.path[len - 1] = '\0';
|
||||
wi->entry.mode = S_IFGITLINK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (iterator__include_trees(wi))
|
||||
return 0;
|
||||
|
||||
return workdir_iterator__advance(NULL, (git_iterator *)wi);
|
||||
}
|
||||
|
||||
int git_iterator_for_workdir(
|
||||
git_iterator **iter,
|
||||
git_iterator **out,
|
||||
git_repository *repo,
|
||||
git_iterator_flag_t flags,
|
||||
const char *start,
|
||||
@ -1182,38 +1254,28 @@ int git_iterator_for_workdir(
|
||||
int error;
|
||||
workdir_iterator *wi;
|
||||
|
||||
assert(iter && repo);
|
||||
if (git_repository__ensure_not_bare(repo, "scan working directory") < 0)
|
||||
return GIT_EBAREREPO;
|
||||
|
||||
if ((error = git_repository__ensure_not_bare(
|
||||
repo, "scan working directory")) < 0)
|
||||
return error;
|
||||
/* initialize as an fs iterator then do overrides */
|
||||
wi = git__calloc(1, sizeof(workdir_iterator));
|
||||
GITERR_CHECK_ALLOC(wi);
|
||||
ITERATOR_BASE_INIT((&wi->fi), fs, FS, repo);
|
||||
|
||||
ITERATOR_BASE_INIT(wi, workdir, WORKDIR, repo);
|
||||
wi->fi.base.type = GIT_ITERATOR_TYPE_WORKDIR;
|
||||
wi->fi.cb.free = workdir_iterator__free;
|
||||
wi->fi.enter_dir_cb = workdir_iterator__enter_dir;
|
||||
wi->fi.leave_dir_cb = workdir_iterator__leave_dir;
|
||||
wi->fi.update_entry_cb = workdir_iterator__update_entry;
|
||||
|
||||
if ((error = iterator__update_ignore_case((git_iterator *)wi, flags)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (git_buf_sets(&wi->path, git_repository_workdir(repo)) < 0 ||
|
||||
git_path_to_dir(&wi->path) < 0 ||
|
||||
git_ignore__for_path(repo, "", &wi->ignores) < 0)
|
||||
if ((error = iterator__update_ignore_case((git_iterator *)wi, flags)) < 0 ||
|
||||
(error = git_ignore__for_path(repo, "", &wi->ignores)) < 0)
|
||||
{
|
||||
git__free(wi);
|
||||
return -1;
|
||||
}
|
||||
wi->root_len = wi->path.size;
|
||||
|
||||
if ((error = workdir_iterator__expand_dir(wi)) < 0) {
|
||||
if (error != GIT_ENOTFOUND)
|
||||
goto fail;
|
||||
giterr_clear();
|
||||
git_iterator_free((git_iterator *)wi);
|
||||
return error;
|
||||
}
|
||||
|
||||
*iter = (git_iterator *)wi;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
git_iterator_free((git_iterator *)wi);
|
||||
return error;
|
||||
return fs_iterator__initialize(out, &wi->fi, git_repository_workdir(repo));
|
||||
}
|
||||
|
||||
|
||||
@ -1315,7 +1377,8 @@ bool git_iterator_current_is_ignored(git_iterator *iter)
|
||||
if (wi->is_ignored != -1)
|
||||
return (bool)(wi->is_ignored != 0);
|
||||
|
||||
if (git_ignore__lookup(&wi->ignores, wi->entry.path, &wi->is_ignored) < 0)
|
||||
if (git_ignore__lookup(
|
||||
&wi->ignores, wi->fi.entry.path, &wi->is_ignored) < 0)
|
||||
wi->is_ignored = true;
|
||||
|
||||
return (bool)wi->is_ignored;
|
||||
@ -1340,10 +1403,10 @@ int git_iterator_current_workdir_path(git_buf **path, git_iterator *iter)
|
||||
{
|
||||
workdir_iterator *wi = (workdir_iterator *)iter;
|
||||
|
||||
if (iter->type != GIT_ITERATOR_TYPE_WORKDIR || !wi->entry.path)
|
||||
if (iter->type != GIT_ITERATOR_TYPE_WORKDIR || !wi->fi.entry.path)
|
||||
*path = NULL;
|
||||
else
|
||||
*path = &wi->path;
|
||||
*path = &wi->fi.path;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ typedef enum {
|
||||
GIT_ITERATOR_TYPE_TREE = 1,
|
||||
GIT_ITERATOR_TYPE_INDEX = 2,
|
||||
GIT_ITERATOR_TYPE_WORKDIR = 3,
|
||||
GIT_ITERATOR_TYPE_FS = 4,
|
||||
} git_iterator_type_t;
|
||||
|
||||
typedef enum {
|
||||
@ -88,6 +89,16 @@ extern int git_iterator_for_workdir(
|
||||
const char *start,
|
||||
const char *end);
|
||||
|
||||
/* for filesystem iterators, you have to explicitly pass in the ignore_case
|
||||
* behavior that you desire
|
||||
*/
|
||||
extern int git_iterator_for_filesystem(
|
||||
git_iterator **out,
|
||||
const char *root,
|
||||
git_iterator_flag_t flags,
|
||||
const char *start,
|
||||
const char *end);
|
||||
|
||||
extern void git_iterator_free(git_iterator *iter);
|
||||
|
||||
/* Return a git_index_entry structure for the current value the iterator
|
||||
|
||||
22
src/odb.c
22
src/odb.c
@ -8,6 +8,7 @@
|
||||
#include "common.h"
|
||||
#include <zlib.h>
|
||||
#include "git2/object.h"
|
||||
#include "git2/sys/odb_backend.h"
|
||||
#include "fileops.h"
|
||||
#include "hash.h"
|
||||
#include "odb.h"
|
||||
@ -407,6 +408,27 @@ int git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority)
|
||||
return add_backend_internal(odb, backend, priority, true, 0);
|
||||
}
|
||||
|
||||
size_t git_odb_num_backends(git_odb *odb)
|
||||
{
|
||||
assert(odb);
|
||||
return odb->backends.length;
|
||||
}
|
||||
|
||||
int git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos)
|
||||
{
|
||||
backend_internal *internal;
|
||||
|
||||
assert(odb && odb);
|
||||
internal = git_vector_get(&odb->backends, pos);
|
||||
|
||||
if (internal && internal->backend) {
|
||||
*out = internal->backend;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
static int add_default_backends(
|
||||
git_odb *db, const char *objects_dir,
|
||||
bool as_alternates, int alternate_depth)
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#include "common.h"
|
||||
#include <zlib.h>
|
||||
#include "git2/object.h"
|
||||
#include "git2/oid.h"
|
||||
#include "git2/sys/odb_backend.h"
|
||||
#include "fileops.h"
|
||||
#include "hash.h"
|
||||
#include "odb.h"
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
#include "common.h"
|
||||
#include <zlib.h>
|
||||
#include "git2/repository.h"
|
||||
#include "git2/oid.h"
|
||||
#include "git2/indexer.h"
|
||||
#include "git2/sys/odb_backend.h"
|
||||
#include "fileops.h"
|
||||
#include "hash.h"
|
||||
#include "odb.h"
|
||||
|
||||
44
src/refdb.c
44
src/refdb.c
@ -7,15 +7,16 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "posix.h"
|
||||
|
||||
#include "git2/object.h"
|
||||
#include "git2/refs.h"
|
||||
#include "git2/refdb.h"
|
||||
#include "git2/sys/refdb_backend.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "refdb.h"
|
||||
#include "refs.h"
|
||||
|
||||
#include "git2/refdb_backend.h"
|
||||
|
||||
int git_refdb_new(git_refdb **out, git_repository *repo)
|
||||
{
|
||||
git_refdb *db;
|
||||
@ -45,7 +46,7 @@ int git_refdb_open(git_refdb **out, git_repository *repo)
|
||||
return -1;
|
||||
|
||||
/* Add the default (filesystem) backend */
|
||||
if (git_refdb_backend_fs(&dir, repo, db) < 0) {
|
||||
if (git_refdb_backend_fs(&dir, repo) < 0) {
|
||||
git_refdb_free(db);
|
||||
return -1;
|
||||
}
|
||||
@ -57,15 +58,19 @@ int git_refdb_open(git_refdb **out, git_repository *repo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_refdb_set_backend(git_refdb *db, git_refdb_backend *backend)
|
||||
static void refdb_free_backend(git_refdb *db)
|
||||
{
|
||||
if (db->backend) {
|
||||
if(db->backend->free)
|
||||
if (db->backend->free)
|
||||
db->backend->free(db->backend);
|
||||
else
|
||||
git__free(db->backend);
|
||||
}
|
||||
}
|
||||
|
||||
int git_refdb_set_backend(git_refdb *db, git_refdb_backend *backend)
|
||||
{
|
||||
refdb_free_backend(db);
|
||||
db->backend = backend;
|
||||
|
||||
return 0;
|
||||
@ -74,23 +79,16 @@ int git_refdb_set_backend(git_refdb *db, git_refdb_backend *backend)
|
||||
int git_refdb_compress(git_refdb *db)
|
||||
{
|
||||
assert(db);
|
||||
|
||||
if (db->backend->compress) {
|
||||
|
||||
if (db->backend->compress)
|
||||
return db->backend->compress(db->backend);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void refdb_free(git_refdb *db)
|
||||
{
|
||||
if (db->backend) {
|
||||
if(db->backend->free)
|
||||
db->backend->free(db->backend);
|
||||
else
|
||||
git__free(db->backend);
|
||||
}
|
||||
|
||||
refdb_free_backend(db);
|
||||
git__free(db);
|
||||
}
|
||||
|
||||
@ -111,9 +109,19 @@ int git_refdb_exists(int *exists, git_refdb *refdb, const char *ref_name)
|
||||
|
||||
int git_refdb_lookup(git_reference **out, git_refdb *db, const char *ref_name)
|
||||
{
|
||||
assert(db && db->backend && ref_name);
|
||||
git_reference *ref;
|
||||
int error;
|
||||
|
||||
return db->backend->lookup(out, db->backend, ref_name);
|
||||
assert(db && db->backend && out && ref_name);
|
||||
|
||||
if (!(error = db->backend->lookup(&ref, db->backend, ref_name))) {
|
||||
ref->db = db;
|
||||
*out = ref;
|
||||
} else {
|
||||
*out = NULL;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_refdb_foreach(
|
||||
|
||||
@ -41,6 +41,6 @@ int git_refdb_foreach_glob(
|
||||
|
||||
int git_refdb_write(git_refdb *refdb, const git_reference *ref);
|
||||
|
||||
int git_refdb_delete(struct git_refdb *refdb, const git_reference *ref);
|
||||
int git_refdb_delete(git_refdb *refdb, const git_reference *ref);
|
||||
|
||||
#endif
|
||||
|
||||
@ -18,7 +18,8 @@
|
||||
#include <git2/tag.h>
|
||||
#include <git2/object.h>
|
||||
#include <git2/refdb.h>
|
||||
#include <git2/refdb_backend.h>
|
||||
#include <git2/sys/refdb_backend.h>
|
||||
#include <git2/sys/refs.h>
|
||||
|
||||
GIT__USE_STRMAP;
|
||||
|
||||
@ -42,7 +43,6 @@ typedef struct refdb_fs_backend {
|
||||
|
||||
git_repository *repo;
|
||||
const char *path;
|
||||
git_refdb *refdb;
|
||||
|
||||
git_refcache refcache;
|
||||
} refdb_fs_backend;
|
||||
@ -62,7 +62,7 @@ static int reference_read(
|
||||
/* Determine the full path of the file */
|
||||
if (git_buf_joinpath(&path, repo_path, ref_name) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
result = git_futils_readbuffer_updated(file_content, path.ptr, mtime, NULL, updated);
|
||||
git_buf_free(&path);
|
||||
|
||||
@ -175,7 +175,7 @@ static int packed_load(refdb_fs_backend *backend)
|
||||
ref_cache->packfile = git_strmap_alloc();
|
||||
GITERR_CHECK_ALLOC(ref_cache->packfile);
|
||||
}
|
||||
|
||||
|
||||
result = reference_read(&packfile, &ref_cache->packfile_time,
|
||||
backend->path, GIT_PACKEDREFS_FILE, &updated);
|
||||
|
||||
@ -193,7 +193,7 @@ static int packed_load(refdb_fs_backend *backend)
|
||||
|
||||
if (result < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
if (!updated)
|
||||
return 0;
|
||||
|
||||
@ -430,12 +430,12 @@ static int loose_lookup(
|
||||
goto done;
|
||||
}
|
||||
|
||||
*out = git_reference__alloc_symbolic(backend->refdb, ref_name, target);
|
||||
*out = git_reference__alloc_symbolic(ref_name, target);
|
||||
} else {
|
||||
if ((error = loose_parse_oid(&oid, &ref_file)) < 0)
|
||||
goto done;
|
||||
|
||||
*out = git_reference__alloc(backend->refdb, ref_name, &oid, NULL);
|
||||
|
||||
*out = git_reference__alloc(ref_name, &oid, NULL);
|
||||
}
|
||||
|
||||
if (*out == NULL)
|
||||
@ -456,19 +456,19 @@ static int packed_map_entry(
|
||||
|
||||
if (packed_load(backend) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
/* Look up on the packfile */
|
||||
packfile_refs = backend->refcache.packfile;
|
||||
|
||||
*pos = git_strmap_lookup_index(packfile_refs, ref_name);
|
||||
|
||||
|
||||
if (!git_strmap_valid_index(packfile_refs, *pos)) {
|
||||
giterr_set(GITERR_REFERENCE, "Reference '%s' not found", ref_name);
|
||||
return GIT_ENOTFOUND;
|
||||
}
|
||||
|
||||
*entry = git_strmap_value_at(packfile_refs, *pos);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -480,14 +480,14 @@ static int packed_lookup(
|
||||
struct packref *entry;
|
||||
khiter_t pos;
|
||||
int error = 0;
|
||||
|
||||
|
||||
if ((error = packed_map_entry(&entry, &pos, backend, ref_name)) < 0)
|
||||
return error;
|
||||
|
||||
if ((*out = git_reference__alloc(backend->refdb, ref_name,
|
||||
if ((*out = git_reference__alloc(ref_name,
|
||||
&entry->oid, &entry->peel)) == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -583,7 +583,7 @@ static int refdb_fs_backend__foreach(
|
||||
git_buf refs_path = GIT_BUF_INIT;
|
||||
const char *ref_name;
|
||||
void *ref = NULL;
|
||||
|
||||
|
||||
GIT_UNUSED(ref);
|
||||
|
||||
assert(_backend);
|
||||
@ -591,7 +591,7 @@ static int refdb_fs_backend__foreach(
|
||||
|
||||
if (packed_load(backend) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
/* list all the packed references first */
|
||||
if (list_type & GIT_REF_OID) {
|
||||
git_strmap_foreach(backend->refcache.packfile, ref_name, ref, {
|
||||
@ -925,7 +925,7 @@ static int refdb_fs_backend__delete(
|
||||
repo = backend->repo;
|
||||
|
||||
/* If a loose reference exists, remove it from the filesystem */
|
||||
|
||||
|
||||
if (git_buf_joinpath(&loose_path, repo->path_repository, ref->name) < 0)
|
||||
return -1;
|
||||
|
||||
@ -933,7 +933,7 @@ static int refdb_fs_backend__delete(
|
||||
error = p_unlink(loose_path.ptr);
|
||||
loose_deleted = 1;
|
||||
}
|
||||
|
||||
|
||||
git_buf_free(&loose_path);
|
||||
|
||||
if (error != 0)
|
||||
@ -947,7 +947,7 @@ static int refdb_fs_backend__delete(
|
||||
|
||||
error = packed_write(backend);
|
||||
}
|
||||
|
||||
|
||||
if (pack_error == GIT_ENOTFOUND)
|
||||
error = loose_deleted ? 0 : GIT_ENOTFOUND;
|
||||
else
|
||||
@ -999,8 +999,7 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend)
|
||||
|
||||
int git_refdb_backend_fs(
|
||||
git_refdb_backend **backend_out,
|
||||
git_repository *repository,
|
||||
git_refdb *refdb)
|
||||
git_repository *repository)
|
||||
{
|
||||
refdb_fs_backend *backend;
|
||||
|
||||
@ -1009,7 +1008,6 @@ int git_refdb_backend_fs(
|
||||
|
||||
backend->repo = repository;
|
||||
backend->path = repository->path_repository;
|
||||
backend->refdb = refdb;
|
||||
|
||||
backend->parent.exists = &refdb_fs_backend__exists;
|
||||
backend->parent.lookup = &refdb_fs_backend__lookup;
|
||||
|
||||
72
src/refs.c
72
src/refs.c
@ -19,7 +19,7 @@
|
||||
#include <git2/branch.h>
|
||||
#include <git2/refs.h>
|
||||
#include <git2/refdb.h>
|
||||
#include <git2/refdb_backend.h>
|
||||
#include <git2/sys/refs.h>
|
||||
|
||||
GIT__USE_STRMAP;
|
||||
|
||||
@ -31,7 +31,7 @@ enum {
|
||||
GIT_PACKREF_WAS_LOOSE = 2
|
||||
};
|
||||
|
||||
static git_reference *alloc_ref(git_refdb *refdb, const char *name)
|
||||
static git_reference *alloc_ref(const char *name)
|
||||
{
|
||||
git_reference *ref;
|
||||
size_t namelen = strlen(name);
|
||||
@ -39,22 +39,19 @@ static git_reference *alloc_ref(git_refdb *refdb, const char *name)
|
||||
if ((ref = git__calloc(1, sizeof(git_reference) + namelen + 1)) == NULL)
|
||||
return NULL;
|
||||
|
||||
ref->db = refdb;
|
||||
memcpy(ref->name, name, namelen + 1);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
git_reference *git_reference__alloc_symbolic(
|
||||
git_refdb *refdb,
|
||||
const char *name,
|
||||
const char *target)
|
||||
const char *name, const char *target)
|
||||
{
|
||||
git_reference *ref;
|
||||
|
||||
assert(refdb && name && target);
|
||||
assert(name && target);
|
||||
|
||||
ref = alloc_ref(refdb, name);
|
||||
ref = alloc_ref(name);
|
||||
if (!ref)
|
||||
return NULL;
|
||||
|
||||
@ -69,16 +66,15 @@ git_reference *git_reference__alloc_symbolic(
|
||||
}
|
||||
|
||||
git_reference *git_reference__alloc(
|
||||
git_refdb *refdb,
|
||||
const char *name,
|
||||
const git_oid *oid,
|
||||
const git_oid *peel)
|
||||
{
|
||||
git_reference *ref;
|
||||
|
||||
assert(refdb && name && oid);
|
||||
assert(name && oid);
|
||||
|
||||
ref = alloc_ref(refdb, name);
|
||||
ref = alloc_ref(name);
|
||||
if (!ref)
|
||||
return NULL;
|
||||
|
||||
@ -258,10 +254,10 @@ int git_reference_lookup_resolved(
|
||||
max_nesting = MAX_NESTING_LEVEL;
|
||||
else if (max_nesting < 0)
|
||||
max_nesting = DEFAULT_NESTING_LEVEL;
|
||||
|
||||
|
||||
strncpy(scan_name, name, GIT_REFNAME_MAX);
|
||||
scan_type = GIT_REF_SYMBOLIC;
|
||||
|
||||
|
||||
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
|
||||
return -1;
|
||||
|
||||
@ -279,7 +275,7 @@ int git_reference_lookup_resolved(
|
||||
|
||||
if ((error = git_refdb_lookup(&ref, refdb, scan_name)) < 0)
|
||||
return error;
|
||||
|
||||
|
||||
scan_type = ref->type;
|
||||
}
|
||||
|
||||
@ -357,7 +353,7 @@ static int reference__create(
|
||||
git_refdb *refdb;
|
||||
git_reference *ref = NULL;
|
||||
int error = 0;
|
||||
|
||||
|
||||
if (ref_out)
|
||||
*ref_out = NULL;
|
||||
|
||||
@ -368,18 +364,19 @@ static int reference__create(
|
||||
|
||||
if (oid != NULL) {
|
||||
assert(symbolic == NULL);
|
||||
ref = git_reference__alloc(refdb, name, oid, NULL);
|
||||
ref = git_reference__alloc(name, oid, NULL);
|
||||
} else {
|
||||
ref = git_reference__alloc_symbolic(refdb, name, symbolic);
|
||||
ref = git_reference__alloc_symbolic(name, symbolic);
|
||||
}
|
||||
|
||||
|
||||
GITERR_CHECK_ALLOC(ref);
|
||||
ref->db = refdb;
|
||||
|
||||
if ((error = git_refdb_write(refdb, ref)) < 0) {
|
||||
git_reference_free(ref);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
if (ref_out == NULL)
|
||||
git_reference_free(ref);
|
||||
else
|
||||
@ -399,17 +396,17 @@ int git_reference_create(
|
||||
int error = 0;
|
||||
|
||||
assert(repo && name && oid);
|
||||
|
||||
|
||||
/* Sanity check the reference being created - target must exist. */
|
||||
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
|
||||
return error;
|
||||
|
||||
|
||||
if (!git_odb_exists(odb, oid)) {
|
||||
giterr_set(GITERR_REFERENCE,
|
||||
"Target OID for the reference doesn't exist on the repository");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return reference__create(ref_out, repo, name, oid, NULL, force);
|
||||
}
|
||||
|
||||
@ -424,7 +421,7 @@ int git_reference_symbolic_create(
|
||||
int error = 0;
|
||||
|
||||
assert(repo && name && target);
|
||||
|
||||
|
||||
if ((error = git_reference__normalize_name_lax(
|
||||
normalized, sizeof(normalized), target)) < 0)
|
||||
return error;
|
||||
@ -438,7 +435,7 @@ int git_reference_set_target(
|
||||
const git_oid *id)
|
||||
{
|
||||
assert(out && ref && id);
|
||||
|
||||
|
||||
if (ref->type != GIT_REF_OID) {
|
||||
giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference");
|
||||
return -1;
|
||||
@ -453,13 +450,13 @@ int git_reference_symbolic_set_target(
|
||||
const char *target)
|
||||
{
|
||||
assert(out && ref && target);
|
||||
|
||||
|
||||
if (ref->type != GIT_REF_SYMBOLIC) {
|
||||
giterr_set(GITERR_REFERENCE,
|
||||
"Cannot set symbolic target on a direct reference");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return git_reference_symbolic_create(out, ref->db->repo, ref->name, target, 1);
|
||||
}
|
||||
|
||||
@ -475,7 +472,7 @@ int git_reference_rename(
|
||||
git_reference *result = NULL;
|
||||
int error = 0;
|
||||
int reference_has_log;
|
||||
|
||||
|
||||
*out = NULL;
|
||||
|
||||
normalization_flags = ref->type == GIT_REF_SYMBOLIC ?
|
||||
@ -490,10 +487,9 @@ int git_reference_rename(
|
||||
* Create the new reference.
|
||||
*/
|
||||
if (ref->type == GIT_REF_OID) {
|
||||
result = git_reference__alloc(ref->db, new_name,
|
||||
&ref->target.oid, &ref->peel);
|
||||
result = git_reference__alloc(new_name, &ref->target.oid, &ref->peel);
|
||||
} else if (ref->type == GIT_REF_SYMBOLIC) {
|
||||
result = git_reference__alloc_symbolic(ref->db, new_name, ref->target.symbolic);
|
||||
result = git_reference__alloc_symbolic(new_name, ref->target.symbolic);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
@ -501,6 +497,8 @@ int git_reference_rename(
|
||||
if (result == NULL)
|
||||
return -1;
|
||||
|
||||
result->db = ref->db;
|
||||
|
||||
/* Check if we have to update HEAD. */
|
||||
if ((error = git_branch_is_head(ref)) < 0)
|
||||
goto on_error;
|
||||
@ -510,11 +508,11 @@ int git_reference_rename(
|
||||
/* Now delete the old ref and save the new one. */
|
||||
if ((error = git_refdb_delete(ref->db, ref)) < 0)
|
||||
goto on_error;
|
||||
|
||||
|
||||
/* Save the new reference. */
|
||||
if ((error = git_refdb_write(ref->db, result)) < 0)
|
||||
goto rollback;
|
||||
|
||||
|
||||
/* Update HEAD it was poiting to the reference being renamed. */
|
||||
if (should_head_be_updated && (error = git_repository_set_head(ref->db->repo, new_name)) < 0) {
|
||||
giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference");
|
||||
@ -548,7 +546,7 @@ int git_reference_resolve(git_reference **ref_out, const git_reference *ref)
|
||||
switch (git_reference_type(ref)) {
|
||||
case GIT_REF_OID:
|
||||
return git_reference_lookup(ref_out, ref->db->repo, ref->name);
|
||||
|
||||
|
||||
case GIT_REF_SYMBOLIC:
|
||||
return git_reference_lookup_resolved(ref_out, ref->db->repo, ref->target.symbolic, -1);
|
||||
|
||||
@ -847,7 +845,7 @@ static int reference__update_terminal(
|
||||
|
||||
if (nesting > MAX_NESTING_LEVEL)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
|
||||
error = git_reference_lookup(&ref, repo, ref_name);
|
||||
|
||||
/* If we haven't found the reference at all, create a new reference. */
|
||||
@ -855,10 +853,10 @@ static int reference__update_terminal(
|
||||
giterr_clear();
|
||||
return git_reference_create(NULL, repo, ref_name, oid, 0);
|
||||
}
|
||||
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
|
||||
/* If the ref is a symbolic reference, follow its target. */
|
||||
if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
|
||||
error = reference__update_terminal(repo, git_reference_symbolic_target(ref), oid,
|
||||
@ -868,7 +866,7 @@ static int reference__update_terminal(
|
||||
git_reference_free(ref);
|
||||
error = git_reference_create(NULL, repo, ref_name, oid, 1);
|
||||
}
|
||||
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
#include "git2/object.h"
|
||||
#include "git2/refdb.h"
|
||||
#include "git2/sys/repository.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "repository.h"
|
||||
@ -129,6 +130,12 @@ static git_repository *repository_alloc(void)
|
||||
return repo;
|
||||
}
|
||||
|
||||
int git_repository_new(git_repository **out)
|
||||
{
|
||||
*out = repository_alloc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_config_data(git_repository *repo)
|
||||
{
|
||||
int is_bare;
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
static int disambiguate_refname(git_reference **out, git_repository *repo, const char *refname)
|
||||
{
|
||||
int error, i;
|
||||
int error = 0, i;
|
||||
bool fallbackmode = true;
|
||||
git_reference *ref;
|
||||
git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT;
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "git2/config.h"
|
||||
#include "git2/sys/config.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/repository.h"
|
||||
#include "git2/index.h"
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "git2/object.h"
|
||||
#include "git2/repository.h"
|
||||
#include "git2/signature.h"
|
||||
#include "git2/odb_backend.h"
|
||||
|
||||
void git_tag__free(git_tag *tag)
|
||||
{
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#include "git2.h"
|
||||
#include "git2/odb_backend.h"
|
||||
|
||||
#include "smart.h"
|
||||
#include "refs.h"
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
/* The OpenBSD realpath function behaves differently */
|
||||
#if !defined(__OpenBSD__)
|
||||
# define p_realpath(p, po) realpath(p, po)
|
||||
#else
|
||||
char *p_realpath(const char *, char *);
|
||||
#endif
|
||||
|
||||
#define p_vsnprintf(b, c, f, a) vsnprintf(b, c, f, a)
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
#ifndef INCLUDE_util_h__
|
||||
#define INCLUDE_util_h__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
|
||||
#define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/sys/config.h"
|
||||
|
||||
void test_config_backend__checks_version(void)
|
||||
{
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/sys/repository.h"
|
||||
|
||||
#include "diff_helpers.h"
|
||||
#include "repository.h"
|
||||
#include "buf_text.h"
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/odb_backend.h"
|
||||
|
||||
#include "fileops.h"
|
||||
#include "odb.h"
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "odb.h"
|
||||
#include "git2/odb_backend.h"
|
||||
|
||||
#include "pack_data_one.h"
|
||||
#include "pack.h"
|
||||
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/odb_backend.h"
|
||||
#include "odb.h"
|
||||
#include "git2/sys/odb_backend.h"
|
||||
|
||||
typedef struct {
|
||||
git_odb_backend base;
|
||||
int position;
|
||||
size_t position;
|
||||
} fake_backend;
|
||||
|
||||
static git_odb_backend *new_backend(int position)
|
||||
static git_odb_backend *new_backend(size_t position)
|
||||
{
|
||||
fake_backend *b;
|
||||
|
||||
@ -22,14 +21,13 @@ static git_odb_backend *new_backend(int position)
|
||||
|
||||
static void check_backend_sorting(git_odb *odb)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < odb->backends.length; ++i) {
|
||||
fake_backend *internal =
|
||||
*((fake_backend **)git_vector_get(&odb->backends, i));
|
||||
size_t i, max_i = git_odb_num_backends(odb);
|
||||
fake_backend *internal;
|
||||
|
||||
for (i = 0; i < max_i; ++i) {
|
||||
cl_git_pass(git_odb_get_backend((git_odb_backend **)&internal, odb, i));
|
||||
cl_assert(internal != NULL);
|
||||
cl_assert(internal->position == (int)i);
|
||||
cl_assert_equal_sz(i, internal->position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "refdb.h"
|
||||
#include "repository.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "posix.h"
|
||||
#include "path.h"
|
||||
#include "refs.h"
|
||||
|
||||
#include "testdb.h"
|
||||
|
||||
#define TEST_REPO_PATH "testrepo"
|
||||
|
||||
static git_repository *repo;
|
||||
static git_refdb *refdb;
|
||||
static git_refdb_backend *refdb_backend;
|
||||
|
||||
int unlink_ref(void *payload, git_buf *file)
|
||||
{
|
||||
@ -27,7 +29,7 @@ int ref_file_foreach(git_repository *repo, int (* cb)(void *payload, git_buf *fi
|
||||
const char *repo_path;
|
||||
git_buf repo_refs_dir = GIT_BUF_INIT;
|
||||
int error = 0;
|
||||
|
||||
|
||||
repo_path = git_repository_path(repo);
|
||||
|
||||
git_buf_joinpath(&repo_refs_dir, repo_path, "HEAD");
|
||||
@ -39,7 +41,7 @@ int ref_file_foreach(git_repository *repo, int (* cb)(void *payload, git_buf *fi
|
||||
git_buf_joinpath(&repo_refs_dir, git_buf_cstr(&repo_refs_dir), "heads");
|
||||
if (git_path_direach(&repo_refs_dir, cb, NULL) != 0)
|
||||
return -1;
|
||||
|
||||
|
||||
git_buf_joinpath(&repo_refs_dir, repo_path, "packed-refs");
|
||||
if (git_path_exists(git_buf_cstr(&repo_refs_dir)) &&
|
||||
cb(NULL, &repo_refs_dir) < 0)
|
||||
@ -53,17 +55,19 @@ int ref_file_foreach(git_repository *repo, int (* cb)(void *payload, git_buf *fi
|
||||
void test_refdb_inmemory__initialize(void)
|
||||
{
|
||||
git_buf repo_refs_dir = GIT_BUF_INIT;
|
||||
git_refdb *refdb;
|
||||
git_refdb_backend *refdb_backend;
|
||||
|
||||
repo = cl_git_sandbox_init(TEST_REPO_PATH);
|
||||
|
||||
cl_git_pass(git_repository_refdb(&refdb, repo));
|
||||
cl_git_pass(refdb_backend_test(&refdb_backend, repo));
|
||||
cl_git_pass(git_refdb_set_backend(refdb, refdb_backend));
|
||||
|
||||
|
||||
|
||||
ref_file_foreach(repo, unlink_ref);
|
||||
|
||||
git_buf_free(&repo_refs_dir);
|
||||
git_refdb_free(refdb);
|
||||
}
|
||||
|
||||
void test_refdb_inmemory__cleanup(void)
|
||||
@ -75,10 +79,10 @@ void test_refdb_inmemory__doesnt_write_ref_file(void)
|
||||
{
|
||||
git_reference *ref;
|
||||
git_oid oid;
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
|
||||
cl_git_pass(git_reference_create(&ref, repo, GIT_REFS_HEADS_DIR "test1", &oid, 0));
|
||||
|
||||
|
||||
ref_file_foreach(repo, empty);
|
||||
|
||||
git_reference_free(ref);
|
||||
@ -88,10 +92,10 @@ void test_refdb_inmemory__read(void)
|
||||
{
|
||||
git_reference *write1, *write2, *write3, *read1, *read2, *read3;
|
||||
git_oid oid1, oid2, oid3;
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
|
||||
cl_git_pass(git_reference_create(&write1, repo, GIT_REFS_HEADS_DIR "test1", &oid1, 0));
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid2, "e90810b8df3e80c413d903f631643c716887138d"));
|
||||
cl_git_pass(git_reference_create(&write2, repo, GIT_REFS_HEADS_DIR "test2", &oid2, 0));
|
||||
|
||||
@ -138,7 +142,7 @@ int foreach_test(const char *ref_name, void *payload)
|
||||
cl_assert(git_oid_cmp(&expected, git_reference_target(ref)) == 0);
|
||||
|
||||
++(*i);
|
||||
|
||||
|
||||
git_reference_free(ref);
|
||||
|
||||
return 0;
|
||||
@ -149,19 +153,19 @@ void test_refdb_inmemory__foreach(void)
|
||||
git_reference *write1, *write2, *write3;
|
||||
git_oid oid1, oid2, oid3;
|
||||
size_t i = 0;
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
|
||||
cl_git_pass(git_reference_create(&write1, repo, GIT_REFS_HEADS_DIR "test1", &oid1, 0));
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid2, "e90810b8df3e80c413d903f631643c716887138d"));
|
||||
cl_git_pass(git_reference_create(&write2, repo, GIT_REFS_HEADS_DIR "test2", &oid2, 0));
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid3, "763d71aadf09a7951596c9746c024e7eece7c7af"));
|
||||
cl_git_pass(git_reference_create(&write3, repo, GIT_REFS_HEADS_DIR "test3", &oid3, 0));
|
||||
|
||||
|
||||
cl_git_pass(git_reference_foreach(repo, GIT_REF_LISTALL, foreach_test, &i));
|
||||
cl_assert_equal_i(i, 3);
|
||||
|
||||
cl_assert_equal_i(3, (int)i);
|
||||
|
||||
git_reference_free(write1);
|
||||
git_reference_free(write2);
|
||||
git_reference_free(write3);
|
||||
@ -174,14 +178,14 @@ int delete_test(const char *ref_name, void *payload)
|
||||
size_t *i = payload;
|
||||
|
||||
cl_git_pass(git_reference_lookup(&ref, repo, ref_name));
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&expected, "e90810b8df3e80c413d903f631643c716887138d"));
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&expected, "e90810b8df3e80c413d903f631643c716887138d"));
|
||||
cl_assert(git_oid_cmp(&expected, git_reference_target(ref)) == 0);
|
||||
|
||||
|
||||
++(*i);
|
||||
|
||||
|
||||
git_reference_free(ref);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -190,24 +194,24 @@ void test_refdb_inmemory__delete(void)
|
||||
git_reference *write1, *write2, *write3;
|
||||
git_oid oid1, oid2, oid3;
|
||||
size_t i = 0;
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid1, "c47800c7266a2be04c571c04d5a6614691ea99bd"));
|
||||
cl_git_pass(git_reference_create(&write1, repo, GIT_REFS_HEADS_DIR "test1", &oid1, 0));
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid2, "e90810b8df3e80c413d903f631643c716887138d"));
|
||||
cl_git_pass(git_reference_create(&write2, repo, GIT_REFS_HEADS_DIR "test2", &oid2, 0));
|
||||
|
||||
|
||||
cl_git_pass(git_oid_fromstr(&oid3, "763d71aadf09a7951596c9746c024e7eece7c7af"));
|
||||
cl_git_pass(git_reference_create(&write3, repo, GIT_REFS_HEADS_DIR "test3", &oid3, 0));
|
||||
|
||||
|
||||
git_reference_delete(write1);
|
||||
git_reference_free(write1);
|
||||
|
||||
|
||||
git_reference_delete(write3);
|
||||
git_reference_free(write3);
|
||||
|
||||
|
||||
cl_git_pass(git_reference_foreach(repo, GIT_REF_LISTALL, delete_test, &i));
|
||||
cl_assert_equal_i(i, 1);
|
||||
cl_assert_equal_i(1, (int)i);
|
||||
|
||||
git_reference_free(write2);
|
||||
}
|
||||
|
||||
@ -1,23 +1,18 @@
|
||||
#include "common.h"
|
||||
#include "vector.h"
|
||||
#include "util.h"
|
||||
#include <git2/refdb.h>
|
||||
#include <git2/refdb_backend.h>
|
||||
#include <git2/errors.h>
|
||||
#include <git2/repository.h>
|
||||
#include "testdb.h"
|
||||
|
||||
typedef struct refdb_test_backend {
|
||||
git_refdb_backend parent;
|
||||
|
||||
|
||||
git_repository *repo;
|
||||
git_refdb *refdb;
|
||||
git_vector refs;
|
||||
} refdb_test_backend;
|
||||
|
||||
typedef struct refdb_test_entry {
|
||||
char *name;
|
||||
git_ref_t type;
|
||||
|
||||
|
||||
union {
|
||||
git_oid oid;
|
||||
char *symbolic;
|
||||
@ -38,19 +33,19 @@ static int refdb_test_backend__exists(
|
||||
refdb_test_backend *backend;
|
||||
refdb_test_entry *entry;
|
||||
size_t i;
|
||||
|
||||
|
||||
assert(_backend);
|
||||
backend = (refdb_test_backend *)_backend;
|
||||
|
||||
|
||||
*exists = 0;
|
||||
|
||||
|
||||
git_vector_foreach(&backend->refs, i, entry) {
|
||||
if (strcmp(entry->name, ref_name) == 0) {
|
||||
*exists = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -60,18 +55,18 @@ static int refdb_test_backend__write(
|
||||
{
|
||||
refdb_test_backend *backend;
|
||||
refdb_test_entry *entry;
|
||||
|
||||
|
||||
assert(_backend);
|
||||
backend = (refdb_test_backend *)_backend;
|
||||
|
||||
entry = git__calloc(1, sizeof(refdb_test_entry));
|
||||
GITERR_CHECK_ALLOC(entry);
|
||||
|
||||
|
||||
entry->name = git__strdup(git_reference_name(ref));
|
||||
GITERR_CHECK_ALLOC(entry->name);
|
||||
|
||||
|
||||
entry->type = git_reference_type(ref);
|
||||
|
||||
|
||||
if (entry->type == GIT_REF_OID)
|
||||
git_oid_cpy(&entry->target.oid, git_reference_target(ref));
|
||||
else {
|
||||
@ -80,7 +75,7 @@ static int refdb_test_backend__write(
|
||||
}
|
||||
|
||||
git_vector_insert(&backend->refs, entry);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -95,21 +90,21 @@ static int refdb_test_backend__lookup(
|
||||
|
||||
assert(_backend);
|
||||
backend = (refdb_test_backend *)_backend;
|
||||
|
||||
|
||||
git_vector_foreach(&backend->refs, i, entry) {
|
||||
if (strcmp(entry->name, ref_name) == 0) {
|
||||
|
||||
if (entry->type == GIT_REF_OID) {
|
||||
*out = git_reference__alloc(backend->refdb, ref_name,
|
||||
*out = git_reference__alloc(ref_name,
|
||||
&entry->target.oid, NULL);
|
||||
} else if (entry->type == GIT_REF_SYMBOLIC) {
|
||||
*out = git_reference__alloc_symbolic(backend->refdb, ref_name,
|
||||
*out = git_reference__alloc_symbolic(ref_name,
|
||||
entry->target.symbolic);
|
||||
}
|
||||
|
||||
if (*out == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -126,21 +121,21 @@ static int refdb_test_backend__foreach(
|
||||
refdb_test_backend *backend;
|
||||
refdb_test_entry *entry;
|
||||
size_t i;
|
||||
|
||||
|
||||
assert(_backend);
|
||||
backend = (refdb_test_backend *)_backend;
|
||||
|
||||
git_vector_foreach(&backend->refs, i, entry) {
|
||||
if (entry->type == GIT_REF_OID && (list_flags & GIT_REF_OID) == 0)
|
||||
continue;
|
||||
|
||||
|
||||
if (entry->type == GIT_REF_SYMBOLIC && (list_flags & GIT_REF_SYMBOLIC) == 0)
|
||||
continue;
|
||||
|
||||
|
||||
if (callback(entry->name, payload) != 0)
|
||||
return GIT_EUSER;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -148,7 +143,7 @@ static void refdb_test_entry_free(refdb_test_entry *entry)
|
||||
{
|
||||
if (entry->type == GIT_REF_SYMBOLIC)
|
||||
git__free(entry->target.symbolic);
|
||||
|
||||
|
||||
git__free(entry->name);
|
||||
git__free(entry);
|
||||
}
|
||||
@ -179,14 +174,14 @@ static void refdb_test_backend__free(git_refdb_backend *_backend)
|
||||
refdb_test_backend *backend;
|
||||
refdb_test_entry *entry;
|
||||
size_t i;
|
||||
|
||||
|
||||
assert(_backend);
|
||||
backend = (refdb_test_backend *)_backend;
|
||||
|
||||
git_vector_foreach(&backend->refs, i, entry)
|
||||
refdb_test_entry_free(entry);
|
||||
|
||||
git_vector_free(&backend->refs);
|
||||
git_vector_free(&backend->refs);
|
||||
git__free(backend);
|
||||
}
|
||||
|
||||
@ -195,19 +190,13 @@ int refdb_backend_test(
|
||||
git_repository *repo)
|
||||
{
|
||||
refdb_test_backend *backend;
|
||||
git_refdb *refdb;
|
||||
int error = 0;
|
||||
|
||||
if ((error = git_repository_refdb(&refdb, repo)) < 0)
|
||||
return error;
|
||||
|
||||
backend = git__calloc(1, sizeof(refdb_test_backend));
|
||||
GITERR_CHECK_ALLOC(backend);
|
||||
|
||||
|
||||
git_vector_init(&backend->refs, 0, ref_name_cmp);
|
||||
|
||||
backend->repo = repo;
|
||||
backend->refdb = refdb;
|
||||
|
||||
backend->parent.exists = &refdb_test_backend__exists;
|
||||
backend->parent.lookup = &refdb_test_backend__lookup;
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
#include <git2/errors.h>
|
||||
#include <git2/repository.h>
|
||||
#include <git2/refdb.h>
|
||||
#include <git2/sys/refs.h>
|
||||
#include <git2/sys/refdb_backend.h>
|
||||
|
||||
int refdb_backend_test(
|
||||
git_refdb_backend **backend_out,
|
||||
git_repository *repo);
|
||||
|
||||
@ -88,4 +88,5 @@ void test_refs_delete__packed_only(void)
|
||||
/* This should pass */
|
||||
cl_git_pass(git_reference_delete(ref));
|
||||
git_reference_free(ref);
|
||||
git_refdb_free(refdb);
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ static void packall(void)
|
||||
|
||||
cl_git_pass(git_repository_refdb(&refdb, g_repo));
|
||||
cl_git_pass(git_refdb_compress(refdb));
|
||||
git_refdb_free(refdb);
|
||||
}
|
||||
|
||||
void test_refs_pack__empty(void)
|
||||
|
||||
@ -284,6 +284,7 @@ void test_refs_rename__overwrite(void)
|
||||
git_reference_free(ref_one);
|
||||
git_reference_free(ref_one_new);
|
||||
git_reference_free(ref_two);
|
||||
git_refdb_free(refdb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -422,7 +422,7 @@ static void build_test_tree(
|
||||
git_treebuilder *builder;
|
||||
const char *scan = fmt, *next;
|
||||
char type, delimiter;
|
||||
git_filemode_t mode;
|
||||
git_filemode_t mode = GIT_FILEMODE_BLOB;
|
||||
git_buf name = GIT_BUF_INIT;
|
||||
va_list arglist;
|
||||
|
||||
@ -755,47 +755,52 @@ void test_repo_iterator__workdir_icase(void)
|
||||
git_iterator_free(i);
|
||||
}
|
||||
|
||||
void test_repo_iterator__workdir_depth(void)
|
||||
static void build_workdir_tree(const char *root, int dirs, int subs)
|
||||
{
|
||||
int i, j;
|
||||
char buf[64], sub[64];
|
||||
|
||||
for (i = 0; i < dirs; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
p_snprintf(buf, sizeof(buf), "%s/dir%02d", root, i);
|
||||
cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH));
|
||||
|
||||
p_snprintf(buf, sizeof(buf), "%s/dir%02d/file", root, i);
|
||||
cl_git_mkfile(buf, buf);
|
||||
buf[strlen(buf) - 5] = '\0';
|
||||
} else {
|
||||
p_snprintf(buf, sizeof(buf), "%s/DIR%02d", root, i);
|
||||
cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH));
|
||||
}
|
||||
|
||||
for (j = 0; j < subs; ++j) {
|
||||
switch (j % 4) {
|
||||
case 0: p_snprintf(sub, sizeof(sub), "%s/sub%02d", buf, j); break;
|
||||
case 1: p_snprintf(sub, sizeof(sub), "%s/sUB%02d", buf, j); break;
|
||||
case 2: p_snprintf(sub, sizeof(sub), "%s/Sub%02d", buf, j); break;
|
||||
case 3: p_snprintf(sub, sizeof(sub), "%s/SUB%02d", buf, j); break;
|
||||
}
|
||||
cl_git_pass(git_futils_mkdir(sub, NULL, 0775, GIT_MKDIR_PATH));
|
||||
|
||||
if (j % 2 == 0) {
|
||||
size_t sublen = strlen(sub);
|
||||
memcpy(&sub[sublen], "/file", sizeof("/file"));
|
||||
cl_git_mkfile(sub, sub);
|
||||
sub[sublen] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_repo_iterator__workdir_depth(void)
|
||||
{
|
||||
git_iterator *iter;
|
||||
char buf[64];
|
||||
|
||||
g_repo = cl_git_sandbox_init("icase");
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
p_snprintf(buf, sizeof(buf), "icase/dir%02d", i);
|
||||
cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH));
|
||||
|
||||
if (i % 2 == 0) {
|
||||
p_snprintf(buf, sizeof(buf), "icase/dir%02d/file", i);
|
||||
cl_git_mkfile(buf, buf);
|
||||
}
|
||||
|
||||
for (j = 0; j < 10; ++j) {
|
||||
p_snprintf(buf, sizeof(buf), "icase/dir%02d/sub%02d", i, j);
|
||||
cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH));
|
||||
|
||||
if (j % 2 == 0) {
|
||||
p_snprintf(
|
||||
buf, sizeof(buf), "icase/dir%02d/sub%02d/file", i, j);
|
||||
cl_git_mkfile(buf, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < 3; ++i) {
|
||||
for (j = 0; j < 50; ++j) {
|
||||
p_snprintf(buf, sizeof(buf), "icase/dir%02d/sub01/moar%02d", i, j);
|
||||
cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH));
|
||||
|
||||
if (j % 2 == 0) {
|
||||
p_snprintf(buf, sizeof(buf),
|
||||
"icase/dir%02d/sub01/moar%02d/file", i, j);
|
||||
cl_git_mkfile(buf, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
build_workdir_tree("icase", 10, 10);
|
||||
build_workdir_tree("icase/DIR01/sUB01", 50, 0);
|
||||
build_workdir_tree("icase/dir02/sUB01", 50, 0);
|
||||
|
||||
/* auto expand with no tree entries */
|
||||
cl_git_pass(git_iterator_for_workdir(&iter, g_repo, 0, NULL, NULL));
|
||||
@ -808,3 +813,114 @@ void test_repo_iterator__workdir_depth(void)
|
||||
expect_iterator_items(iter, 337, NULL, 337, NULL);
|
||||
git_iterator_free(iter);
|
||||
}
|
||||
|
||||
void test_repo_iterator__fs(void)
|
||||
{
|
||||
git_iterator *i;
|
||||
static const char *expect_base[] = {
|
||||
"DIR01/Sub02/file",
|
||||
"DIR01/sub00/file",
|
||||
"current_file",
|
||||
"dir00/Sub02/file",
|
||||
"dir00/file",
|
||||
"dir00/sub00/file",
|
||||
"modified_file",
|
||||
"new_file",
|
||||
NULL,
|
||||
};
|
||||
static const char *expect_trees[] = {
|
||||
"DIR01/",
|
||||
"DIR01/SUB03/",
|
||||
"DIR01/Sub02/",
|
||||
"DIR01/Sub02/file",
|
||||
"DIR01/sUB01/",
|
||||
"DIR01/sub00/",
|
||||
"DIR01/sub00/file",
|
||||
"current_file",
|
||||
"dir00/",
|
||||
"dir00/SUB03/",
|
||||
"dir00/Sub02/",
|
||||
"dir00/Sub02/file",
|
||||
"dir00/file",
|
||||
"dir00/sUB01/",
|
||||
"dir00/sub00/",
|
||||
"dir00/sub00/file",
|
||||
"modified_file",
|
||||
"new_file",
|
||||
NULL,
|
||||
};
|
||||
static const char *expect_noauto[] = {
|
||||
"DIR01/",
|
||||
"current_file",
|
||||
"dir00/",
|
||||
"modified_file",
|
||||
"new_file",
|
||||
NULL,
|
||||
};
|
||||
|
||||
g_repo = cl_git_sandbox_init("status");
|
||||
|
||||
build_workdir_tree("status/subdir", 2, 4);
|
||||
|
||||
cl_git_pass(git_iterator_for_filesystem(
|
||||
&i, "status/subdir", 0, NULL, NULL));
|
||||
expect_iterator_items(i, 8, expect_base, 8, expect_base);
|
||||
git_iterator_free(i);
|
||||
|
||||
cl_git_pass(git_iterator_for_filesystem(
|
||||
&i, "status/subdir", GIT_ITERATOR_INCLUDE_TREES, NULL, NULL));
|
||||
expect_iterator_items(i, 18, expect_trees, 18, expect_trees);
|
||||
git_iterator_free(i);
|
||||
|
||||
cl_git_pass(git_iterator_for_filesystem(
|
||||
&i, "status/subdir", GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL));
|
||||
expect_iterator_items(i, 5, expect_noauto, 18, expect_trees);
|
||||
git_iterator_free(i);
|
||||
|
||||
git__tsort((void **)expect_base, 8, (git__tsort_cmp)git__strcasecmp);
|
||||
git__tsort((void **)expect_trees, 18, (git__tsort_cmp)git__strcasecmp);
|
||||
git__tsort((void **)expect_noauto, 5, (git__tsort_cmp)git__strcasecmp);
|
||||
|
||||
cl_git_pass(git_iterator_for_filesystem(
|
||||
&i, "status/subdir", GIT_ITERATOR_IGNORE_CASE, NULL, NULL));
|
||||
expect_iterator_items(i, 8, expect_base, 8, expect_base);
|
||||
git_iterator_free(i);
|
||||
|
||||
cl_git_pass(git_iterator_for_filesystem(
|
||||
&i, "status/subdir", GIT_ITERATOR_IGNORE_CASE |
|
||||
GIT_ITERATOR_INCLUDE_TREES, NULL, NULL));
|
||||
expect_iterator_items(i, 18, expect_trees, 18, expect_trees);
|
||||
git_iterator_free(i);
|
||||
|
||||
cl_git_pass(git_iterator_for_filesystem(
|
||||
&i, "status/subdir", GIT_ITERATOR_IGNORE_CASE |
|
||||
GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL));
|
||||
expect_iterator_items(i, 5, expect_noauto, 18, expect_trees);
|
||||
git_iterator_free(i);
|
||||
}
|
||||
|
||||
void test_repo_iterator__fs2(void)
|
||||
{
|
||||
git_iterator *i;
|
||||
static const char *expect_base[] = {
|
||||
"heads/br2",
|
||||
"heads/dir",
|
||||
"heads/master",
|
||||
"heads/packed-test",
|
||||
"heads/subtrees",
|
||||
"heads/test",
|
||||
"tags/e90810b",
|
||||
"tags/foo/bar",
|
||||
"tags/foo/foo/bar",
|
||||
"tags/point_to_blob",
|
||||
"tags/test",
|
||||
NULL,
|
||||
};
|
||||
|
||||
g_repo = cl_git_sandbox_init("testrepo");
|
||||
|
||||
cl_git_pass(git_iterator_for_filesystem(
|
||||
&i, "testrepo/.git/refs", 0, NULL, NULL));
|
||||
expect_iterator_items(i, 11, expect_base, 11, expect_base);
|
||||
git_iterator_free(i);
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/sys/repository.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "posix.h"
|
||||
#include "util.h"
|
||||
|
||||
@ -146,6 +146,8 @@ void retrieve_top_stash_id(git_oid *out)
|
||||
cl_git_pass(git_reference_name_to_id(out, repo, GIT_REFS_STASH_FILE));
|
||||
|
||||
cl_assert_equal_i(true, git_oid_cmp(out, git_object_id(top_stash)) == 0);
|
||||
|
||||
git_object_free(top_stash);
|
||||
}
|
||||
|
||||
void test_stash_drop__dropping_the_top_stash_updates_the_stash_reference(void)
|
||||
@ -165,4 +167,6 @@ void test_stash_drop__dropping_the_top_stash_updates_the_stash_reference(void)
|
||||
retrieve_top_stash_id(&oid);
|
||||
|
||||
cl_git_pass(git_oid_cmp(&oid, git_object_id(next_top_stash)));
|
||||
|
||||
git_object_free(next_top_stash);
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/sys/repository.h"
|
||||
|
||||
#include "fileops.h"
|
||||
#include "ignore.h"
|
||||
#include "status_helpers.h"
|
||||
@ -321,10 +323,10 @@ void test_status_worktree_init__new_staged_file_must_handle_crlf(void)
|
||||
cl_set_cleanup(&cleanup_new_repo, "getting_started");
|
||||
cl_git_pass(git_repository_init(&repo, "getting_started", 0));
|
||||
|
||||
// Ensure that repo has core.autocrlf=true
|
||||
/* Ensure that repo has core.autocrlf=true */
|
||||
cl_repo_set_bool(repo, "core.autocrlf", true);
|
||||
|
||||
cl_git_mkfile("getting_started/testfile.txt", "content\r\n"); // Content with CRLF
|
||||
cl_git_mkfile("getting_started/testfile.txt", "content\r\n"); /* Content with CRLF */
|
||||
|
||||
cl_git_pass(git_repository_index(&index, repo));
|
||||
cl_git_pass(git_index_add_bypath(index, "testfile.txt"));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user