1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
|
/*
* 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_merge_h__
#define INCLUDE_sys_git_merge_h__
#include "git2/common.h"
#include "git2/types.h"
#include "git2/index.h"
#include "git2/merge.h"
/**
* @file git2/sys/merge.h
* @brief Custom merge drivers
* @defgroup git_merge Custom merge drivers
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* A "merge driver" is a mechanism that can be configured to handle
* conflict resolution for files changed in both the "ours" and "theirs"
* side of a merge.
*/
typedef struct git_merge_driver git_merge_driver;
/**
* Look up a merge driver by name
*
* @param name The name of the merge driver
* @return Pointer to the merge driver object or NULL if not found
*/
GIT_EXTERN(git_merge_driver *) git_merge_driver_lookup(const char *name);
/** The "text" merge driver */
#define GIT_MERGE_DRIVER_TEXT "text"
/** The "binary" merge driver */
#define GIT_MERGE_DRIVER_BINARY "binary"
/** The "union" merge driver */
#define GIT_MERGE_DRIVER_UNION "union"
/**
* A merge driver source represents the file to be merged
*/
typedef struct git_merge_driver_source git_merge_driver_source;
/**
* Get the repository that the source data is coming from.
*
* @param src the merge driver source
* @return the repository
*/
GIT_EXTERN(git_repository *) git_merge_driver_source_repo(
const git_merge_driver_source *src);
/**
* Gets the ancestor of the file to merge.
*
* @param src the merge driver source
* @return the ancestor or NULL if there was no ancestor
*/
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_ancestor(
const git_merge_driver_source *src);
/**
* Gets the ours side of the file to merge.
*
* @param src the merge driver source
* @return the ours side or NULL if there was no ours side
*/
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_ours(
const git_merge_driver_source *src);
/**
* Gets the theirs side of the file to merge.
*
* @param src the merge driver source
* @return the theirs side or NULL if there was no theirs side
*/
GIT_EXTERN(const git_index_entry *) git_merge_driver_source_theirs(
const git_merge_driver_source *src);
/**
* Gets the merge file options that the merge was invoked with.
*
* @param src the merge driver source
* @return the options
*/
GIT_EXTERN(const git_merge_file_options *) git_merge_driver_source_file_options(
const git_merge_driver_source *src);
/**
* Initialize callback on merge driver
*
* Specified as `driver.initialize`, this is an optional callback invoked
* before a merge driver is first used. It will be called once at most
* per library lifetime.
*
* If non-NULL, the merge driver's `initialize` callback will be invoked
* right before the first use of the driver, so you can defer expensive
* initialization operations (in case libgit2 is being used in a way that
* doesn't need the merge driver).
*
* @param self the merge driver to initialize
* @return 0 on success, or a negative number on failure
*/
typedef int GIT_CALLBACK(git_merge_driver_init_fn)(git_merge_driver *self);
/**
* Shutdown callback on merge driver
*
* Specified as `driver.shutdown`, this is an optional callback invoked
* when the merge driver is unregistered or when libgit2 is shutting down.
* It will be called once at most and should release resources as needed.
* This may be called even if the `initialize` callback was not made.
*
* Typically this function will free the `git_merge_driver` object itself.
*
* @param self the merge driver to shutdown
*/
typedef void GIT_CALLBACK(git_merge_driver_shutdown_fn)(git_merge_driver *self);
/**
* Callback to perform the merge.
*
* Specified as `driver.apply`, this is the callback that actually does the
* merge. If it can successfully perform a merge, it should populate
* `path_out` with a pointer to the filename to accept, `mode_out` with
* the resultant mode, and `merged_out` with the buffer of the merged file
* and then return 0. If the driver returns `GIT_PASSTHROUGH`, then the
* default merge driver should instead be run. It can also return
* `GIT_EMERGECONFLICT` if the driver is not able to produce a merge result,
* and the file will remain conflicted. Any other errors will fail and
* return to the caller.
*
* The `filter_name` contains the name of the filter that was invoked, as
* specified by the file's attributes.
*
* The `src` contains the data about the file to be merged.
*
* @param self the merge driver
* @param path_out the resolved path
* @param mode_out the resolved mode
* @param merged_out the merged output contents
* @param filter_name the filter that was invoked
* @param src the data about the unmerged file
* @return 0 on success, or an error code
*/
typedef int GIT_CALLBACK(git_merge_driver_apply_fn)(
git_merge_driver *self,
const char **path_out,
uint32_t *mode_out,
git_buf *merged_out,
const char *filter_name,
const git_merge_driver_source *src);
/**
* Merge driver structure used to register custom merge drivers.
*
* To associate extra data with a driver, allocate extra data and put the
* `git_merge_driver` struct at the start of your data buffer, then cast
* the `self` pointer to your larger structure when your callback is invoked.
*/
struct git_merge_driver {
/** The `version` should be set to `GIT_MERGE_DRIVER_VERSION`. */
unsigned int version;
/** Called when the merge driver is first used for any file. */
git_merge_driver_init_fn initialize;
/** Called when the merge driver is unregistered from the system. */
git_merge_driver_shutdown_fn shutdown;
/**
* Called to merge the contents of a conflict. If this function
* returns `GIT_PASSTHROUGH` then the default (`text`) merge driver
* will instead be invoked. If this function returns
* `GIT_EMERGECONFLICT` then the file will remain conflicted.
*/
git_merge_driver_apply_fn apply;
};
/** The version for the `git_merge_driver` */
#define GIT_MERGE_DRIVER_VERSION 1
/**
* Register a merge driver under a given name.
*
* As mentioned elsewhere, the initialize callback will not be invoked
* immediately. It is deferred until the driver is used in some way.
*
* Currently the merge driver registry is not thread safe, so any
* registering or deregistering of merge drivers must be done outside of
* any possible usage of the drivers (i.e. during application setup or
* shutdown).
*
* @param name The name of this driver to match an attribute. Attempting
* to register with an in-use name will return GIT_EEXISTS.
* @param driver The merge driver definition. This pointer will be stored
* as is by libgit2 so it must be a durable allocation (either
* static or on the heap).
* @return 0 on successful registry, error code <0 on failure
*/
GIT_EXTERN(int) git_merge_driver_register(
const char *name, git_merge_driver *driver);
/**
* Remove the merge driver with the given name.
*
* Attempting to remove the builtin libgit2 merge drivers is not permitted
* and will return an error.
*
* Currently the merge driver registry is not thread safe, so any
* registering or deregistering of drivers must be done outside of any
* possible usage of the drivers (i.e. during application setup or shutdown).
*
* @param name The name under which the merge driver was registered
* @return 0 on success, error code <0 on failure
*/
GIT_EXTERN(int) git_merge_driver_unregister(const char *name);
/** @} */
GIT_END_DECL
#endif
|