git/apply.c

/*
 * apply.c
 *
 * Copyright (C) Linus Torvalds, 2005
 *
 * This applies patches on top of some (arbitrary) version of the SCM.
 *
 */

#define USE_THE_REPOSITORY_VARIABLE

#include "git-compat-util.h"
#include "abspath.h"
#include "base85.h"
#include "config.h"
#include "object-store-ll.h"
#include "delta.h"
#include "diff.h"
#include "dir.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "xdiff-interface.h"
#include "merge-ll.h"
#include "lockfile.h"
#include "name-hash.h"
#include "object-name.h"
#include "object-file.h"
#include "parse-options.h"
#include "path.h"
#include "quote.h"
#include "read-cache.h"
#include "repository.h"
#include "rerere.h"
#include "apply.h"
#include "entry.h"
#include "setup.h"
#include "symlinks.h"
#include "wildmatch.h"
#include "ws.h"

struct gitdiff_data {};

static void git_apply_config(void)
{}

static int parse_whitespace_option(struct apply_state *state, const char *option)
{}

static int parse_ignorewhitespace_option(struct apply_state *state,
						 const char *option)
{}

int init_apply_state(struct apply_state *state,
		     struct repository *repo,
		     const char *prefix)
{}

void clear_apply_state(struct apply_state *state)
{}

static void mute_routine(const char *msg UNUSED, va_list params UNUSED)
{}

int check_apply_state(struct apply_state *state, int force_apply)
{}

static void set_default_whitespace_mode(struct apply_state *state)
{}

/*
 * This represents one "hunk" from a patch, starting with
 * "@@ -oldpos,oldlines +newpos,newlines @@" marker.  The
 * patch text is pointed at by patch, and its byte length
 * is stored in size.  leading and trailing are the number
 * of context lines.
 */
struct fragment {};

/*
 * When dealing with a binary patch, we reuse "leading" field
 * to store the type of the binary hunk, either deflated "delta"
 * or deflated "literal".
 */
#define binary_patch_method
#define BINARY_DELTA_DEFLATED
#define BINARY_LITERAL_DEFLATED

static void free_fragment_list(struct fragment *list)
{}

void release_patch(struct patch *patch)
{}

static void free_patch(struct patch *patch)
{}

static void free_patch_list(struct patch *list)
{}

/*
 * A line in a file, len-bytes long (includes the terminating LF,
 * except for an incomplete line at the end if the file ends with
 * one), and its contents hashes to 'hash'.
 */
struct line {};

/*
 * This represents a "file", which is an array of "lines".
 */
struct image {};
#define IMAGE_INIT

static void image_init(struct image *image)
{}

static void image_clear(struct image *image)
{}

static uint32_t hash_line(const char *cp, size_t len)
{}

static void image_add_line(struct image *img, const char *bol, size_t len, unsigned flag)
{}

/*
 * "buf" has the file contents to be patched (read from various sources).
 * attach it to "image" and add line-based index to it.
 * "image" now owns the "buf".
 */
static void image_prepare(struct image *image, char *buf, size_t len,
			  int prepare_linetable)
{}

static void image_remove_first_line(struct image *img)
{}

static void image_remove_last_line(struct image *img)
{}

/* fmt must contain _one_ %s and no other substitution */
static void say_patch_name(FILE *output, const char *fmt, struct patch *patch)
{}

#define SLOP

/*
 * apply.c isn't equipped to handle arbitrarily large patches, because
 * it intermingles `unsigned long` with `int` for the type used to store
 * buffer lengths.
 *
 * Only process patches that are just shy of 1 GiB large in order to
 * avoid any truncation or overflow issues.
 */
#define MAX_APPLY_SIZE

static int read_patch_file(struct strbuf *sb, int fd)
{}

static unsigned long linelen(const char *buffer, unsigned long size)
{}

static int is_dev_null(const char *str)
{}

#define TERM_SPACE
#define TERM_TAB

static int name_terminate(int c, int terminate)
{}

/* remove double slashes to make --index work with such filenames */
static char *squash_slash(char *name)
{}

static char *find_name_gnu(struct strbuf *root,
			   const char *line,
			   int p_value)
{}

static size_t sane_tz_len(const char *line, size_t len)
{}

static size_t tz_with_colon_len(const char *line, size_t len)
{}

static size_t date_len(const char *line, size_t len)
{}

static size_t short_time_len(const char *line, size_t len)
{}

static size_t fractional_time_len(const char *line, size_t len)
{}

static size_t trailing_spaces_len(const char *line, size_t len)
{}

static size_t diff_timestamp_len(const char *line, size_t len)
{}

static char *find_name_common(struct strbuf *root,
			      const char *line,
			      const char *def,
			      int p_value,
			      const char *end,
			      int terminate)
{}

static char *find_name(struct strbuf *root,
		       const char *line,
		       char *def,
		       int p_value,
		       int terminate)
{}

static char *find_name_traditional(struct strbuf *root,
				   const char *line,
				   char *def,
				   int p_value)
{}

/*
 * Given the string after "--- " or "+++ ", guess the appropriate
 * p_value for the given patch.
 */
static int guess_p_value(struct apply_state *state, const char *nameline)
{}

/*
 * Does the ---/+++ line have the POSIX timestamp after the last HT?
 * GNU diff puts epoch there to signal a creation/deletion event.  Is
 * this such a timestamp?
 */
static int has_epoch_timestamp(const char *nameline)
{}

/*
 * Get the name etc info from the ---/+++ lines of a traditional patch header
 *
 * FIXME! The end-of-filename heuristics are kind of screwy. For existing
 * files, we can happily check the index for a match, but for creating a
 * new file we should try to match whatever "patch" does. I have no idea.
 */
static int parse_traditional_patch(struct apply_state *state,
				   const char *first,
				   const char *second,
				   struct patch *patch)
{}

static int gitdiff_hdrend(struct gitdiff_data *state UNUSED,
			  const char *line UNUSED,
			  struct patch *patch UNUSED)
{}

/*
 * We're anal about diff header consistency, to make
 * sure that we don't end up having strange ambiguous
 * patches floating around.
 *
 * As a result, gitdiff_{old|new}name() will check
 * their names against any previous information, just
 * to make sure..
 */
#define DIFF_OLD_NAME
#define DIFF_NEW_NAME

static int gitdiff_verify_name(struct gitdiff_data *state,
			       const char *line,
			       int isnull,
			       char **name,
			       int side)
{}

static int gitdiff_oldname(struct gitdiff_data *state,
			   const char *line,
			   struct patch *patch)
{}

static int gitdiff_newname(struct gitdiff_data *state,
			   const char *line,
			   struct patch *patch)
{}

static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
{}

static int gitdiff_oldmode(struct gitdiff_data *state,
			   const char *line,
			   struct patch *patch)
{}

static int gitdiff_newmode(struct gitdiff_data *state,
			   const char *line,
			   struct patch *patch)
{}

static int gitdiff_delete(struct gitdiff_data *state,
			  const char *line,
			  struct patch *patch)
{}

static int gitdiff_newfile(struct gitdiff_data *state,
			   const char *line,
			   struct patch *patch)
{}

static int gitdiff_copysrc(struct gitdiff_data *state,
			   const char *line,
			   struct patch *patch)
{}

static int gitdiff_copydst(struct gitdiff_data *state,
			   const char *line,
			   struct patch *patch)
{}

static int gitdiff_renamesrc(struct gitdiff_data *state,
			     const char *line,
			     struct patch *patch)
{}

static int gitdiff_renamedst(struct gitdiff_data *state,
			     const char *line,
			     struct patch *patch)
{}

static int gitdiff_similarity(struct gitdiff_data *state UNUSED,
			      const char *line,
			      struct patch *patch)
{}

static int gitdiff_dissimilarity(struct gitdiff_data *state UNUSED,
				 const char *line,
				 struct patch *patch)
{}

static int gitdiff_index(struct gitdiff_data *state,
			 const char *line,
			 struct patch *patch)
{}

/*
 * This is normal for a diff that doesn't change anything: we'll fall through
 * into the next diff. Tell the parser to break out.
 */
static int gitdiff_unrecognized(struct gitdiff_data *state UNUSED,
				const char *line UNUSED,
				struct patch *patch UNUSED)
{}

/*
 * Skip p_value leading components from "line"; as we do not accept
 * absolute paths, return NULL in that case.
 */
static const char *skip_tree_prefix(int p_value,
				    const char *line,
				    int llen)
{}

/*
 * This is to extract the same name that appears on "diff --git"
 * line.  We do not find and return anything if it is a rename
 * patch, and it is OK because we will find the name elsewhere.
 * We need to reliably find name only when it is mode-change only,
 * creation or deletion of an empty file.  In any of these cases,
 * both sides are the same name under a/ and b/ respectively.
 */
static char *git_header_name(int p_value,
			     const char *line,
			     int llen)
{}

static int check_header_line(int linenr, struct patch *patch)
{}

int parse_git_diff_header(struct strbuf *root,
			  int *linenr,
			  int p_value,
			  const char *line,
			  int len,
			  unsigned int size,
			  struct patch *patch)
{}

static int parse_num(const char *line, unsigned long *p)
{}

static int parse_range(const char *line, int len, int offset, const char *expect,
		       unsigned long *p1, unsigned long *p2)
{}

static void recount_diff(const char *line, int size, struct fragment *fragment)
{}

/*
 * Parse a unified diff fragment header of the
 * form "@@ -a,b +c,d @@"
 */
static int parse_fragment_header(const char *line, int len, struct fragment *fragment)
{}

/*
 * Find file diff header
 *
 * Returns:
 *  -1 if no header was found
 *  -128 in case of error
 *   the size of the header in bytes (called "offset") otherwise
 */
static int find_header(struct apply_state *state,
		       const char *line,
		       unsigned long size,
		       int *hdrsize,
		       struct patch *patch)
{}

static void record_ws_error(struct apply_state *state,
			    unsigned result,
			    const char *line,
			    int len,
			    int linenr)
{}

static void check_whitespace(struct apply_state *state,
			     const char *line,
			     int len,
			     unsigned ws_rule)
{}

/*
 * Check if the patch has context lines with CRLF or
 * the patch wants to remove lines with CRLF.
 */
static void check_old_for_crlf(struct patch *patch, const char *line, int len)
{}


/*
 * Parse a unified diff. Note that this really needs to parse each
 * fragment separately, since the only way to know the difference
 * between a "---" that is part of a patch, and a "---" that starts
 * the next patch is to look at the line counts..
 */
static int parse_fragment(struct apply_state *state,
			  const char *line,
			  unsigned long size,
			  struct patch *patch,
			  struct fragment *fragment)
{}

/*
 * We have seen "diff --git a/... b/..." header (or a traditional patch
 * header).  Read hunks that belong to this patch into fragments and hang
 * them to the given patch structure.
 *
 * The (fragment->patch, fragment->size) pair points into the memory given
 * by the caller, not a copy, when we return.
 *
 * Returns:
 *   -1 in case of error,
 *   the number of bytes in the patch otherwise.
 */
static int parse_single_patch(struct apply_state *state,
			      const char *line,
			      unsigned long size,
			      struct patch *patch)
{}

static inline int metadata_changes(struct patch *patch)
{}

static char *inflate_it(const void *data, unsigned long size,
			unsigned long inflated_size)
{}

/*
 * Read a binary hunk and return a new fragment; fragment->patch
 * points at an allocated memory that the caller must free, so
 * it is marked as "->free_patch = 1".
 */
static struct fragment *parse_binary_hunk(struct apply_state *state,
					  char **buf_p,
					  unsigned long *sz_p,
					  int *status_p,
					  int *used_p)
{}

/*
 * Returns:
 *   -1 in case of error,
 *   the length of the parsed binary patch otherwise
 */
static int parse_binary(struct apply_state *state,
			char *buffer,
			unsigned long size,
			struct patch *patch)
{}

static void prefix_one(struct apply_state *state, char **name)
{}

static void prefix_patch(struct apply_state *state, struct patch *p)
{}

/*
 * include/exclude
 */

static void add_name_limit(struct apply_state *state,
			   const char *name,
			   int exclude)
{}

static int use_patch(struct apply_state *state, struct patch *p)
{}

/*
 * Read the patch text in "buffer" that extends for "size" bytes; stop
 * reading after seeing a single patch (i.e. changes to a single file).
 * Create fragments (i.e. patch hunks) and hang them to the given patch.
 *
 * Returns:
 *   -1 if no header was found or parse_binary() failed,
 *   -128 on another error,
 *   the number of bytes consumed otherwise,
 *     so that the caller can call us again for the next patch.
 */
static int parse_chunk(struct apply_state *state, char *buffer, unsigned long size, struct patch *patch)
{}

static void reverse_patches(struct patch *p)
{}

static const char pluses[] =;
static const char minuses[]=;

static void show_stats(struct apply_state *state, struct patch *patch)
{}

static int read_old_data(struct stat *st, struct patch *patch,
			 const char *path, struct strbuf *buf)
{}

/*
 * Update the preimage, and the common lines in postimage,
 * from buffer buf of length len.
 */
static void update_pre_post_images(struct image *preimage,
				   struct image *postimage,
				   char *buf, size_t len)
{}

/*
 * Compare lines s1 of length n1 and s2 of length n2, ignoring
 * whitespace difference. Returns 1 if they match, 0 otherwise
 */
static int fuzzy_matchlines(const char *s1, size_t n1,
			    const char *s2, size_t n2)
{}

static int line_by_line_fuzzy_match(struct image *img,
				    struct image *preimage,
				    struct image *postimage,
				    unsigned long current,
				    int current_lno,
				    int preimage_limit)
{}

static int match_fragment(struct apply_state *state,
			  struct image *img,
			  struct image *preimage,
			  struct image *postimage,
			  unsigned long current,
			  int current_lno,
			  unsigned ws_rule,
			  int match_beginning, int match_end)
{}

static int find_pos(struct apply_state *state,
		    struct image *img,
		    struct image *preimage,
		    struct image *postimage,
		    int line,
		    unsigned ws_rule,
		    int match_beginning, int match_end)
{}

/*
 * The change from "preimage" and "postimage" has been found to
 * apply at applied_pos (counts in line numbers) in "img".
 * Update "img" to remove "preimage" and replace it with "postimage".
 */
static void update_image(struct apply_state *state,
			 struct image *img,
			 int applied_pos,
			 struct image *preimage,
			 struct image *postimage)
{}

/*
 * Use the patch-hunk text in "frag" to prepare two images (preimage and
 * postimage) for the hunk.  Find lines that match "preimage" in "img" and
 * replace the part of "img" with "postimage" text.
 */
static int apply_one_fragment(struct apply_state *state,
			      struct image *img, struct fragment *frag,
			      int inaccurate_eof, unsigned ws_rule,
			      int nth_fragment)
{}

static int apply_binary_fragment(struct apply_state *state,
				 struct image *img,
				 struct patch *patch)
{}

/*
 * Replace "img" with the result of applying the binary patch.
 * The binary patch data itself in patch->fragment is still kept
 * but the preimage prepared by the caller in "img" is freed here
 * or in the helper function apply_binary_fragment() this calls.
 */
static int apply_binary(struct apply_state *state,
			struct image *img,
			struct patch *patch)
{}

static int apply_fragments(struct apply_state *state, struct image *img, struct patch *patch)
{}

static int read_blob_object(struct strbuf *buf, const struct object_id *oid, unsigned mode)
{}

static int read_file_or_gitlink(const struct cache_entry *ce, struct strbuf *buf)
{}

static struct patch *in_fn_table(struct apply_state *state, const char *name)
{}

/*
 * item->util in the filename table records the status of the path.
 * Usually it points at a patch (whose result records the contents
 * of it after applying it), but it could be PATH_WAS_DELETED for a
 * path that a previously applied patch has already removed, or
 * PATH_TO_BE_DELETED for a path that a later patch would remove.
 *
 * The latter is needed to deal with a case where two paths A and B
 * are swapped by first renaming A to B and then renaming B to A;
 * moving A to B should not be prevented due to presence of B as we
 * will remove it in a later patch.
 */
#define PATH_TO_BE_DELETED
#define PATH_WAS_DELETED

static int to_be_deleted(struct patch *patch)
{}

static int was_deleted(struct patch *patch)
{}

static void add_to_fn_table(struct apply_state *state, struct patch *patch)
{}

static void prepare_fn_table(struct apply_state *state, struct patch *patch)
{}

static int checkout_target(struct index_state *istate,
			   struct cache_entry *ce, struct stat *st)
{}

static struct patch *previous_patch(struct apply_state *state,
				    struct patch *patch,
				    int *gone)
{}

static int verify_index_match(struct apply_state *state,
			      const struct cache_entry *ce,
			      struct stat *st)
{}

#define SUBMODULE_PATCH_WITHOUT_INDEX

static int load_patch_target(struct apply_state *state,
			     struct strbuf *buf,
			     const struct cache_entry *ce,
			     struct stat *st,
			     struct patch *patch,
			     const char *name,
			     unsigned expected_mode)
{}

/*
 * We are about to apply "patch"; populate the "image" with the
 * current version we have, from the working tree or from the index,
 * depending on the situation e.g. --cached/--index.  If we are
 * applying a non-git patch that incrementally updates the tree,
 * we read from the result of a previous diff.
 */
static int load_preimage(struct apply_state *state,
			 struct image *image,
			 struct patch *patch, struct stat *st,
			 const struct cache_entry *ce)
{}

static int resolve_to(struct image *image, const struct object_id *result_id)
{}

static int three_way_merge(struct apply_state *state,
			   struct image *image,
			   char *path,
			   const struct object_id *base,
			   const struct object_id *ours,
			   const struct object_id *theirs)
{}

/*
 * When directly falling back to add/add three-way merge, we read from
 * the current contents of the new_name.  In no cases other than that
 * this function will be called.
 */
static int load_current(struct apply_state *state,
			struct image *image,
			struct patch *patch)
{}

static int try_threeway(struct apply_state *state,
			struct image *image,
			struct patch *patch,
			struct stat *st,
			const struct cache_entry *ce)
{}

static int apply_data(struct apply_state *state, struct patch *patch,
		      struct stat *st, const struct cache_entry *ce)
{}

/*
 * If "patch" that we are looking at modifies or deletes what we have,
 * we would want it not to lose any local modification we have, either
 * in the working tree or in the index.
 *
 * This also decides if a non-git patch is a creation patch or a
 * modification to an existing empty file.  We do not check the state
 * of the current tree for a creation patch in this function; the caller
 * check_patch() separately makes sure (and errors out otherwise) that
 * the path the patch creates does not exist in the current tree.
 */
static int check_preimage(struct apply_state *state,
			  struct patch *patch,
			  struct cache_entry **ce,
			  struct stat *st)
{}


#define EXISTS_IN_INDEX
#define EXISTS_IN_WORKTREE
#define EXISTS_IN_INDEX_AS_ITA

static int check_to_create(struct apply_state *state,
			   const char *new_name,
			   int ok_if_exists)
{}

static void prepare_symlink_changes(struct apply_state *state, struct patch *patch)
{}

static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *name)
{}

static int path_is_beyond_symlink(struct apply_state *state, const char *name_)
{}

static int check_unsafe_path(struct patch *patch)
{}

/*
 * Check and apply the patch in-core; leave the result in patch->result
 * for the caller to write it out to the final destination.
 */
static int check_patch(struct apply_state *state, struct patch *patch)
{}

static int check_patch_list(struct apply_state *state, struct patch *patch)
{}

static int read_apply_cache(struct apply_state *state)
{}

/* This function tries to read the object name from the current index */
static int get_current_oid(struct apply_state *state, const char *path,
			   struct object_id *oid)
{}

static int preimage_oid_in_gitlink_patch(struct patch *p, struct object_id *oid)
{}

/* Build an index that contains just the files needed for a 3way merge */
static int build_fake_ancestor(struct apply_state *state, struct patch *list)
{}

static void stat_patch_list(struct apply_state *state, struct patch *patch)
{}

static void numstat_patch_list(struct apply_state *state,
			       struct patch *patch)
{}

static void show_file_mode_name(const char *newdelete, unsigned int mode, const char *name)
{}

static void show_mode_change(struct patch *p, int show_name)
{}

static void show_rename_copy(struct patch *p)
{}

static void summary_patch_list(struct patch *patch)
{}

static void patch_stats(struct apply_state *state, struct patch *patch)
{}

static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty)
{}

static int add_index_file(struct apply_state *state,
			  const char *path,
			  unsigned mode,
			  void *buf,
			  unsigned long size)
{}

/*
 * Returns:
 *  -1 if an unrecoverable error happened
 *   0 if everything went well
 *   1 if a recoverable error happened
 */
static int try_create_file(struct apply_state *state, const char *path,
			   unsigned int mode, const char *buf,
			   unsigned long size)
{}

/*
 * We optimistically assume that the directories exist,
 * which is true 99% of the time anyway. If they don't,
 * we create them and try again.
 *
 * Returns:
 *   -1 on error
 *   0 otherwise
 */
static int create_one_file(struct apply_state *state,
			   char *path,
			   unsigned mode,
			   const char *buf,
			   unsigned long size)
{}

static int add_conflicted_stages_file(struct apply_state *state,
				       struct patch *patch)
{}

static int create_file(struct apply_state *state, struct patch *patch)
{}

/* phase zero is to remove, phase one is to create */
static int write_out_one_result(struct apply_state *state,
				struct patch *patch,
				int phase)
{}

static int write_out_one_reject(struct apply_state *state, struct patch *patch)
{}

/*
 * Returns:
 *  -1 if an error happened
 *   0 if the patch applied cleanly
 *   1 if the patch did not apply cleanly
 */
static int write_out_results(struct apply_state *state, struct patch *list)
{}

/*
 * Try to apply a patch.
 *
 * Returns:
 *  -128 if a bad error happened (like patch unreadable)
 *  -1 if patch did not apply and user cannot deal with it
 *   0 if the patch applied
 *   1 if the patch did not apply but user might fix it
 */
static int apply_patch(struct apply_state *state,
		       int fd,
		       const char *filename,
		       int options)
{}

static int apply_option_parse_exclude(const struct option *opt,
				      const char *arg, int unset)
{}

static int apply_option_parse_include(const struct option *opt,
				      const char *arg, int unset)
{}

static int apply_option_parse_p(const struct option *opt,
				const char *arg,
				int unset)
{}

static int apply_option_parse_space_change(const struct option *opt,
					   const char *arg, int unset)
{}

static int apply_option_parse_whitespace(const struct option *opt,
					 const char *arg, int unset)
{}

static int apply_option_parse_directory(const struct option *opt,
					const char *arg, int unset)
{}

int apply_all_patches(struct apply_state *state,
		      int argc,
		      const char **argv,
		      int options)
{}

int apply_parse_options(int argc, const char **argv,
			struct apply_state *state,
			int *force_apply, int *options,
			const char * const *apply_usage)
{}