2 * Copyright (C) 2005 Junio C Hamano
15 struct userdiff_driver
;
17 /* This header file is internal between diff.c and its diff transformers
18 * (e.g. diffcore-rename, diffcore-pickaxe). Never include this header
22 /* A range [start, end). Lines are numbered starting at 0. */
27 /* A set of ranges. The ranges must always be disjoint and sorted. */
29 unsigned int alloc
, nr
;
33 /* We internally use unsigned short as the score value,
34 * and rely on an int capable to hold 32-bits. -B can take
35 * -Bmerge_score/break_score format and the two scores are
36 * passed around in one int (high 16-bit for merge and low 16-bit
39 #define MAX_SCORE 60000.0
40 #define DEFAULT_RENAME_SCORE 30000 /* rename/copy similarity minimum (50%) */
41 #define DEFAULT_BREAK_SCORE 30000 /* minimum for break to happen (50%) */
42 #define DEFAULT_MERGE_SCORE 36000 /* maximum for break-merge to happen (60%) */
44 #define MINIMUM_BREAK_SIZE 400 /* do not break a file smaller than this */
47 * the internal representation for a single file (blob). It records the blob
48 * object name (if known -- for a work tree file it typically is a NUL SHA-1),
49 * filemode and pathname. This is what the `diff_addremove()`, `diff_change()`
50 * and `diff_unmerge()` synthesize and feed `diff_queue()` function with.
52 struct diff_filespec
{
58 int count
; /* Reference count */
59 int rename_used
; /* Count of rename users */
60 unsigned short mode
; /* file mode */
61 unsigned oid_valid
: 1; /* if true, use oid and trust mode;
62 * if false, use the name and read from
65 #define DIFF_FILE_VALID(spec) (((spec)->mode) != 0)
66 unsigned should_free
: 1; /* data should be free()'ed */
67 unsigned should_munmap
: 1; /* data should be munmap()'ed */
68 unsigned dirty_submodule
: 2; /* For submodules: its work tree is dirty */
69 #define DIRTY_SUBMODULE_UNTRACKED 1
70 #define DIRTY_SUBMODULE_MODIFIED 2
71 unsigned is_stdin
: 1;
72 unsigned has_more_entries
: 1; /* only appear in combined diff */
73 /* data should be considered "binary"; -1 means "don't know yet" */
74 signed int is_binary
: 2;
75 struct userdiff_driver
*driver
;
78 struct diff_filespec
*alloc_filespec(const char *);
79 void free_filespec(struct diff_filespec
*);
80 void fill_filespec(struct diff_filespec
*, const struct object_id
*,
84 * Prefetch the entries in diff_queued_diff. The parameter is a pointer to a
87 void diff_queued_diff_prefetch(void *repository
);
89 struct diff_populate_filespec_options
{
90 unsigned check_size_only
: 1;
91 unsigned check_binary
: 1;
94 * If an object is missing, diff_populate_filespec() will invoke this
95 * callback before attempting to read that object again.
97 void (*missing_object_cb
)(void *);
98 void *missing_object_data
;
100 int diff_populate_filespec(struct repository
*, struct diff_filespec
*,
101 const struct diff_populate_filespec_options
*);
102 void diff_free_filespec_data(struct diff_filespec
*);
103 void diff_free_filespec_blob(struct diff_filespec
*);
104 int diff_filespec_is_binary(struct repository
*, struct diff_filespec
*);
107 * This records a pair of `struct diff_filespec`; the filespec for a file in
108 * the "old" set (i.e. preimage) is called `one`, and the filespec for a file
109 * in the "new" set (i.e. postimage) is called `two`. A change that represents
110 * file creation has NULL in `one`, and file deletion has NULL in `two`.
112 * A `filepair` starts pointing at `one` and `two` that are from the same
113 * filename, but `diffcore_std()` can break pairs and match component filespecs
114 * with other filespecs from a different filepair to form new filepair. This is
115 * called 'rename detection'.
117 struct diff_filepair
{
118 struct diff_filespec
*one
;
119 struct diff_filespec
*two
;
121 * Tracked line ranges for -L filtering; borrowed from
122 * line_log_data and must not be freed.
124 const struct range_set
*line_ranges
;
125 unsigned short int score
;
126 char status
; /* M C R A D U etc. (see Documentation/diff-format.adoc or DIFF_STATUS_* in diff.h) */
127 unsigned broken_pair
: 1;
128 unsigned renamed_pair
: 1;
129 unsigned is_unmerged
: 1;
130 unsigned done_skip_stat_unmatch
: 1;
131 unsigned skip_stat_unmatch_result
: 1;
134 #define DIFF_PAIR_UNMERGED(p) ((p)->is_unmerged)
136 #define DIFF_PAIR_RENAME(p) ((p)->renamed_pair)
138 #define DIFF_PAIR_BROKEN(p) \
139 ( (!DIFF_FILE_VALID((p)->one) != !DIFF_FILE_VALID((p)->two)) && \
140 ((p)->broken_pair != 0) )
142 #define DIFF_PAIR_TYPE_CHANGED(p) \
143 ((S_IFMT & (p)->one->mode) != (S_IFMT & (p)->two->mode))
145 #define DIFF_PAIR_MODE_CHANGED(p) ((p)->one->mode != (p)->two->mode)
147 void diff_free_filepair(struct diff_filepair
*);
148 void pool_diff_free_filepair(struct mem_pool
*pool
,
149 struct diff_filepair
*p
);
151 int diff_unmodified_pair(struct diff_filepair
*);
154 * This is a collection of filepairs. Notable members are:
157 * An array of pointers to `struct diff_filepair`. This dynamically grows as
161 * The allocated size of the `queue` array;
164 * The number of elements in the `queue` array.
166 struct diff_queue_struct
{
167 struct diff_filepair
**queue
;
172 #define DIFF_QUEUE_INIT { 0 }
174 void diff_queue_init(struct diff_queue_struct
*q
);
175 void diff_queue_clear(struct diff_queue_struct
*q
);
177 extern struct diff_queue_struct diff_queued_diff
;
178 struct diff_filepair
*diff_queue(struct diff_queue_struct
*,
179 struct diff_filespec
*,
180 struct diff_filespec
*);
181 void diff_q(struct diff_queue_struct
*, struct diff_filepair
*);
183 /* dir_rename_relevance: the reason we want rename information for a dir */
184 enum dir_rename_relevance
{
186 RELEVANT_FOR_ANCESTOR
= 1,
187 RELEVANT_FOR_SELF
= 2
189 /* file_rename_relevance: the reason(s) we want rename information for a file */
190 enum file_rename_relevance
{
191 RELEVANT_NO_MORE
= 0, /* i.e. NOT relevant */
192 RELEVANT_CONTENT
= 1,
193 RELEVANT_LOCATION
= 2
196 void partial_clear_dir_rename_count(struct strmap
*dir_rename_count
);
198 void diffcore_break(struct repository
*, int);
199 void diffcore_rename(struct diff_options
*);
200 void diffcore_rename_extended(struct diff_options
*options
,
201 struct mem_pool
*pool
,
202 struct strintmap
*relevant_sources
,
203 struct strintmap
*dirs_removed
,
204 struct strmap
*dir_rename_count
,
205 struct strmap
*cached_pairs
);
206 void diffcore_merge_broken(void);
207 void diffcore_pickaxe(struct diff_options
*);
208 void diffcore_order(const char *orderfile
);
209 void diffcore_rotate(struct diff_options
*);
211 /* low-level interface to diffcore_order */
213 void *obj
; /* setup by caller */
215 /* setup/used by order_objects() */
220 typedef const char *(*obj_path_fn_t
)(void *obj
);
222 void order_objects(const char *orderfile
, obj_path_fn_t obj_path
,
223 struct obj_order
*objs
, int nr
);
227 void diff_debug_filespec(struct diff_filespec
*, int, const char *);
228 void diff_debug_filepair(const struct diff_filepair
*, int);
229 void diff_debug_queue(const char *, struct diff_queue_struct
*);
231 #define diff_debug_filespec(a,b,c) do { /* nothing */ } while (0)
232 #define diff_debug_filepair(a,b) do { /* nothing */ } while (0)
233 #define diff_debug_queue(a,b) do { /* nothing */ } while (0)
236 int diffcore_count_changes(struct repository
*r
,
237 struct diff_filespec
*src
,
238 struct diff_filespec
*dst
,
241 unsigned long *src_copied
,
242 unsigned long *literal_added
);
245 * If filespec contains an OID and if that object is missing from the given
246 * repository, add that OID to to_fetch.
248 void diff_add_if_missing(struct repository
*r
,
249 struct oid_array
*to_fetch
,
250 const struct diff_filespec
*filespec
);