THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

422 lines
11KB

  1. /*
  2. * Low level 3-way in-core file merge.
  3. *
  4. * Copyright (c) 2007 Junio C Hamano
  5. */
  6. #include "cache.h"
  7. #include "config.h"
  8. #include "attr.h"
  9. #include "xdiff-interface.h"
  10. #include "run-command.h"
  11. #include "ll-merge.h"
  12. #include "quote.h"
  13. struct ll_merge_driver;
  14. typedef int (*ll_merge_fn)(const struct ll_merge_driver *,
  15. mmbuffer_t *result,
  16. const char *path,
  17. mmfile_t *orig, const char *orig_name,
  18. mmfile_t *src1, const char *name1,
  19. mmfile_t *src2, const char *name2,
  20. const struct ll_merge_options *opts,
  21. int marker_size);
  22. struct ll_merge_driver {
  23. const char *name;
  24. const char *description;
  25. ll_merge_fn fn;
  26. const char *recursive;
  27. struct ll_merge_driver *next;
  28. char *cmdline;
  29. };
  30. static struct attr_check *merge_attributes;
  31. static struct attr_check *load_merge_attributes(void)
  32. {
  33. if (!merge_attributes)
  34. merge_attributes = attr_check_initl("merge", "conflict-marker-size", NULL);
  35. return merge_attributes;
  36. }
  37. void reset_merge_attributes(void)
  38. {
  39. attr_check_free(merge_attributes);
  40. merge_attributes = NULL;
  41. }
  42. /*
  43. * Built-in low-levels
  44. */
  45. static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
  46. mmbuffer_t *result,
  47. const char *path,
  48. mmfile_t *orig, const char *orig_name,
  49. mmfile_t *src1, const char *name1,
  50. mmfile_t *src2, const char *name2,
  51. const struct ll_merge_options *opts,
  52. int marker_size)
  53. {
  54. mmfile_t *stolen;
  55. assert(opts);
  56. /*
  57. * The tentative merge result is the common ancestor for an
  58. * internal merge. For the final merge, it is "ours" by
  59. * default but -Xours/-Xtheirs can tweak the choice.
  60. */
  61. if (opts->virtual_ancestor) {
  62. stolen = orig;
  63. } else {
  64. switch (opts->variant) {
  65. default:
  66. warning("Cannot merge binary files: %s (%s vs. %s)",
  67. path, name1, name2);
  68. /* fallthru */
  69. case XDL_MERGE_FAVOR_OURS:
  70. stolen = src1;
  71. break;
  72. case XDL_MERGE_FAVOR_THEIRS:
  73. stolen = src2;
  74. break;
  75. }
  76. }
  77. result->ptr = stolen->ptr;
  78. result->size = stolen->size;
  79. stolen->ptr = NULL;
  80. /*
  81. * With -Xtheirs or -Xours, we have cleanly merged;
  82. * otherwise we got a conflict.
  83. */
  84. return (opts->variant ? 0 : 1);
  85. }
  86. static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
  87. mmbuffer_t *result,
  88. const char *path,
  89. mmfile_t *orig, const char *orig_name,
  90. mmfile_t *src1, const char *name1,
  91. mmfile_t *src2, const char *name2,
  92. const struct ll_merge_options *opts,
  93. int marker_size)
  94. {
  95. xmparam_t xmp;
  96. assert(opts);
  97. if (orig->size > MAX_XDIFF_SIZE ||
  98. src1->size > MAX_XDIFF_SIZE ||
  99. src2->size > MAX_XDIFF_SIZE ||
  100. buffer_is_binary(orig->ptr, orig->size) ||
  101. buffer_is_binary(src1->ptr, src1->size) ||
  102. buffer_is_binary(src2->ptr, src2->size)) {
  103. return ll_binary_merge(drv_unused, result,
  104. path,
  105. orig, orig_name,
  106. src1, name1,
  107. src2, name2,
  108. opts, marker_size);
  109. }
  110. memset(&xmp, 0, sizeof(xmp));
  111. xmp.level = XDL_MERGE_ZEALOUS;
  112. xmp.favor = opts->variant;
  113. xmp.xpp.flags = opts->xdl_opts;
  114. if (git_xmerge_style >= 0)
  115. xmp.style = git_xmerge_style;
  116. if (marker_size > 0)
  117. xmp.marker_size = marker_size;
  118. xmp.ancestor = orig_name;
  119. xmp.file1 = name1;
  120. xmp.file2 = name2;
  121. return xdl_merge(orig, src1, src2, &xmp, result);
  122. }
  123. static int ll_union_merge(const struct ll_merge_driver *drv_unused,
  124. mmbuffer_t *result,
  125. const char *path_unused,
  126. mmfile_t *orig, const char *orig_name,
  127. mmfile_t *src1, const char *name1,
  128. mmfile_t *src2, const char *name2,
  129. const struct ll_merge_options *opts,
  130. int marker_size)
  131. {
  132. /* Use union favor */
  133. struct ll_merge_options o;
  134. assert(opts);
  135. o = *opts;
  136. o.variant = XDL_MERGE_FAVOR_UNION;
  137. return ll_xdl_merge(drv_unused, result, path_unused,
  138. orig, NULL, src1, NULL, src2, NULL,
  139. &o, marker_size);
  140. }
  141. #define LL_BINARY_MERGE 0
  142. #define LL_TEXT_MERGE 1
  143. #define LL_UNION_MERGE 2
  144. static struct ll_merge_driver ll_merge_drv[] = {
  145. { "binary", "built-in binary merge", ll_binary_merge },
  146. { "text", "built-in 3-way text merge", ll_xdl_merge },
  147. { "union", "built-in union merge", ll_union_merge },
  148. };
  149. static void create_temp(mmfile_t *src, char *path, size_t len)
  150. {
  151. int fd;
  152. xsnprintf(path, len, ".merge_file_XXXXXX");
  153. fd = xmkstemp(path);
  154. if (write_in_full(fd, src->ptr, src->size) < 0)
  155. die_errno("unable to write temp-file");
  156. close(fd);
  157. }
  158. /*
  159. * User defined low-level merge driver support.
  160. */
  161. static int ll_ext_merge(const struct ll_merge_driver *fn,
  162. mmbuffer_t *result,
  163. const char *path,
  164. mmfile_t *orig, const char *orig_name,
  165. mmfile_t *src1, const char *name1,
  166. mmfile_t *src2, const char *name2,
  167. const struct ll_merge_options *opts,
  168. int marker_size)
  169. {
  170. char temp[4][50];
  171. struct strbuf cmd = STRBUF_INIT;
  172. struct strbuf_expand_dict_entry dict[6];
  173. struct strbuf path_sq = STRBUF_INIT;
  174. const char *args[] = { NULL, NULL };
  175. int status, fd, i;
  176. struct stat st;
  177. assert(opts);
  178. sq_quote_buf(&path_sq, path);
  179. dict[0].placeholder = "O"; dict[0].value = temp[0];
  180. dict[1].placeholder = "A"; dict[1].value = temp[1];
  181. dict[2].placeholder = "B"; dict[2].value = temp[2];
  182. dict[3].placeholder = "L"; dict[3].value = temp[3];
  183. dict[4].placeholder = "P"; dict[4].value = path_sq.buf;
  184. dict[5].placeholder = NULL; dict[5].value = NULL;
  185. if (fn->cmdline == NULL)
  186. die("custom merge driver %s lacks command line.", fn->name);
  187. result->ptr = NULL;
  188. result->size = 0;
  189. create_temp(orig, temp[0], sizeof(temp[0]));
  190. create_temp(src1, temp[1], sizeof(temp[1]));
  191. create_temp(src2, temp[2], sizeof(temp[2]));
  192. xsnprintf(temp[3], sizeof(temp[3]), "%d", marker_size);
  193. strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
  194. args[0] = cmd.buf;
  195. status = run_command_v_opt(args, RUN_USING_SHELL);
  196. fd = open(temp[1], O_RDONLY);
  197. if (fd < 0)
  198. goto bad;
  199. if (fstat(fd, &st))
  200. goto close_bad;
  201. result->size = st.st_size;
  202. result->ptr = xmallocz(result->size);
  203. if (read_in_full(fd, result->ptr, result->size) != result->size) {
  204. FREE_AND_NULL(result->ptr);
  205. result->size = 0;
  206. }
  207. close_bad:
  208. close(fd);
  209. bad:
  210. for (i = 0; i < 3; i++)
  211. unlink_or_warn(temp[i]);
  212. strbuf_release(&cmd);
  213. strbuf_release(&path_sq);
  214. return status;
  215. }
  216. /*
  217. * merge.default and merge.driver configuration items
  218. */
  219. static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;
  220. static const char *default_ll_merge;
  221. static int read_merge_config(const char *var, const char *value, void *cb)
  222. {
  223. struct ll_merge_driver *fn;
  224. const char *key, *name;
  225. int namelen;
  226. if (!strcmp(var, "merge.default"))
  227. return git_config_string(&default_ll_merge, var, value);
  228. /*
  229. * We are not interested in anything but "merge.<name>.variable";
  230. * especially, we do not want to look at variables such as
  231. * "merge.summary", "merge.tool", and "merge.verbosity".
  232. */
  233. if (parse_config_key(var, "merge", &name, &namelen, &key) < 0 || !name)
  234. return 0;
  235. /*
  236. * Find existing one as we might be processing merge.<name>.var2
  237. * after seeing merge.<name>.var1.
  238. */
  239. for (fn = ll_user_merge; fn; fn = fn->next)
  240. if (!strncmp(fn->name, name, namelen) && !fn->name[namelen])
  241. break;
  242. if (!fn) {
  243. fn = xcalloc(1, sizeof(struct ll_merge_driver));
  244. fn->name = xmemdupz(name, namelen);
  245. fn->fn = ll_ext_merge;
  246. *ll_user_merge_tail = fn;
  247. ll_user_merge_tail = &(fn->next);
  248. }
  249. if (!strcmp("name", key))
  250. return git_config_string(&fn->description, var, value);
  251. if (!strcmp("driver", key)) {
  252. if (!value)
  253. return error("%s: lacks value", var);
  254. /*
  255. * merge.<name>.driver specifies the command line:
  256. *
  257. * command-line
  258. *
  259. * The command-line will be interpolated with the following
  260. * tokens and is given to the shell:
  261. *
  262. * %O - temporary file name for the merge base.
  263. * %A - temporary file name for our version.
  264. * %B - temporary file name for the other branches' version.
  265. * %L - conflict marker length
  266. * %P - the original path (safely quoted for the shell)
  267. *
  268. * The external merge driver should write the results in the
  269. * file named by %A, and signal that it has done with zero exit
  270. * status.
  271. */
  272. fn->cmdline = xstrdup(value);
  273. return 0;
  274. }
  275. if (!strcmp("recursive", key))
  276. return git_config_string(&fn->recursive, var, value);
  277. return 0;
  278. }
  279. static void initialize_ll_merge(void)
  280. {
  281. if (ll_user_merge_tail)
  282. return;
  283. ll_user_merge_tail = &ll_user_merge;
  284. git_config(read_merge_config, NULL);
  285. }
  286. static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr)
  287. {
  288. struct ll_merge_driver *fn;
  289. const char *name;
  290. int i;
  291. initialize_ll_merge();
  292. if (ATTR_TRUE(merge_attr))
  293. return &ll_merge_drv[LL_TEXT_MERGE];
  294. else if (ATTR_FALSE(merge_attr))
  295. return &ll_merge_drv[LL_BINARY_MERGE];
  296. else if (ATTR_UNSET(merge_attr)) {
  297. if (!default_ll_merge)
  298. return &ll_merge_drv[LL_TEXT_MERGE];
  299. else
  300. name = default_ll_merge;
  301. }
  302. else
  303. name = merge_attr;
  304. for (fn = ll_user_merge; fn; fn = fn->next)
  305. if (!strcmp(fn->name, name))
  306. return fn;
  307. for (i = 0; i < ARRAY_SIZE(ll_merge_drv); i++)
  308. if (!strcmp(ll_merge_drv[i].name, name))
  309. return &ll_merge_drv[i];
  310. /* default to the 3-way */
  311. return &ll_merge_drv[LL_TEXT_MERGE];
  312. }
  313. static void normalize_file(mmfile_t *mm, const char *path, struct index_state *istate)
  314. {
  315. struct strbuf strbuf = STRBUF_INIT;
  316. if (renormalize_buffer(istate, path, mm->ptr, mm->size, &strbuf)) {
  317. free(mm->ptr);
  318. mm->size = strbuf.len;
  319. mm->ptr = strbuf_detach(&strbuf, NULL);
  320. }
  321. }
  322. int ll_merge(mmbuffer_t *result_buf,
  323. const char *path,
  324. mmfile_t *ancestor, const char *ancestor_label,
  325. mmfile_t *ours, const char *our_label,
  326. mmfile_t *theirs, const char *their_label,
  327. struct index_state *istate,
  328. const struct ll_merge_options *opts)
  329. {
  330. struct attr_check *check = load_merge_attributes();
  331. static const struct ll_merge_options default_opts;
  332. const char *ll_driver_name = NULL;
  333. int marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
  334. const struct ll_merge_driver *driver;
  335. if (!opts)
  336. opts = &default_opts;
  337. if (opts->renormalize) {
  338. normalize_file(ancestor, path, istate);
  339. normalize_file(ours, path, istate);
  340. normalize_file(theirs, path, istate);
  341. }
  342. git_check_attr(istate, path, check);
  343. ll_driver_name = check->items[0].value;
  344. if (check->items[1].value) {
  345. marker_size = atoi(check->items[1].value);
  346. if (marker_size <= 0)
  347. marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
  348. }
  349. driver = find_ll_merge_driver(ll_driver_name);
  350. if (opts->virtual_ancestor) {
  351. if (driver->recursive)
  352. driver = find_ll_merge_driver(driver->recursive);
  353. }
  354. if (opts->extra_marker_size) {
  355. marker_size += opts->extra_marker_size;
  356. }
  357. return driver->fn(driver, result_buf, path, ancestor, ancestor_label,
  358. ours, our_label, theirs, their_label,
  359. opts, marker_size);
  360. }
  361. int ll_merge_marker_size(struct index_state *istate, const char *path)
  362. {
  363. static struct attr_check *check;
  364. int marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
  365. if (!check)
  366. check = attr_check_initl("conflict-marker-size", NULL);
  367. git_check_attr(istate, path, check);
  368. if (check->items[0].value) {
  369. marker_size = atoi(check->items[0].value);
  370. if (marker_size <= 0)
  371. marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
  372. }
  373. return marker_size;
  374. }