From 7fb0eaa289576a1dcd7751015ba791f1bce778a9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Jan 2010 20:39:59 -0800 Subject: git_attr(): fix function signature The function took (name, namelen) as its arguments, but all the public callers wanted to pass a full string. Demote the counted-string interface to an internal API status, and allow public callers to just pass the string to the function. Signed-off-by: Junio C Hamano diff --git a/archive.c b/archive.c index 55b2732..a9ebdc5 100644 --- a/archive.c +++ b/archive.c @@ -87,8 +87,8 @@ static void setup_archive_check(struct git_attr_check *check) static struct git_attr *attr_export_subst; if (!attr_export_ignore) { - attr_export_ignore = git_attr("export-ignore", 13); - attr_export_subst = git_attr("export-subst", 12); + attr_export_ignore = git_attr("export-ignore"); + attr_export_subst = git_attr("export-subst"); } check[0].attr = attr_export_ignore; check[1].attr = attr_export_subst; diff --git a/attr.c b/attr.c index 55bdb7c..f5346ed 100644 --- a/attr.c +++ b/attr.c @@ -65,7 +65,7 @@ static int invalid_attr_name(const char *name, int namelen) return 0; } -struct git_attr *git_attr(const char *name, int len) +static struct git_attr *git_attr_internal(const char *name, int len) { unsigned hval = hash_name(name, len); unsigned pos = hval % HASHSIZE; @@ -95,6 +95,11 @@ struct git_attr *git_attr(const char *name, int len) return a; } +struct git_attr *git_attr(const char *name) +{ + return git_attr_internal(name, strlen(name)); +} + /* * .gitattributes file is one line per record, each of which is * @@ -162,7 +167,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp, else { e->setto = xmemdupz(equals + 1, ep - equals - 1); } - e->attr = git_attr(cp, len); + e->attr = git_attr_internal(cp, len); } (*num_attr)++; return ep + strspn(ep, blank); @@ -221,7 +226,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, sizeof(struct attr_state) * num_attr + (is_macro ? 0 : namelen + 1)); if (is_macro) - res->u.attr = git_attr(name, namelen); + res->u.attr = git_attr_internal(name, namelen); else { res->u.pattern = (char *)&(res->state[num_attr]); memcpy(res->u.pattern, name, namelen); diff --git a/attr.h b/attr.h index 69b5767..450f49d 100644 --- a/attr.h +++ b/attr.h @@ -8,7 +8,7 @@ struct git_attr; * Given a string, return the gitattribute object that * corresponds to it. */ -struct git_attr *git_attr(const char *, int); +struct git_attr *git_attr(const char *); /* Internal use */ extern const char git_attr__true[]; diff --git a/builtin-check-attr.c b/builtin-check-attr.c index 8bd0430..3016d29 100644 --- a/builtin-check-attr.c +++ b/builtin-check-attr.c @@ -106,7 +106,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) const char *name; struct git_attr *a; name = argv[i]; - a = git_attr(name, strlen(name)); + a = git_attr(name); if (!a) return error("%s: not a valid attribute name", name); check[i].attr = a; diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 4429d53..9beff35 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -673,7 +673,7 @@ static void setup_delta_attr_check(struct git_attr_check *check) static struct git_attr *attr_delta; if (!attr_delta) - attr_delta = git_attr("delta", 5); + attr_delta = git_attr("delta"); check[0].attr = attr_delta; } diff --git a/convert.c b/convert.c index 491e714..852fd64 100644 --- a/convert.c +++ b/convert.c @@ -377,9 +377,9 @@ static void setup_convert_check(struct git_attr_check *check) static struct git_attr *attr_filter; if (!attr_crlf) { - attr_crlf = git_attr("crlf", 4); - attr_ident = git_attr("ident", 5); - attr_filter = git_attr("filter", 6); + attr_crlf = git_attr("crlf"); + attr_ident = git_attr("ident"); + attr_filter = git_attr("filter"); user_convert_tail = &user_convert; git_config(read_convert_config, NULL); } diff --git a/ll-merge.c b/ll-merge.c index 2d6b6d6..f4b0a07 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -344,7 +344,7 @@ static const char *git_path_check_merge(const char *path) static struct git_attr_check attr_merge_check; if (!attr_merge_check.attr) - attr_merge_check.attr = git_attr("merge", 5); + attr_merge_check.attr = git_attr("merge"); if (git_checkattr(path, 1, &attr_merge_check)) return NULL; diff --git a/userdiff.c b/userdiff.c index 57529ae..df99249 100644 --- a/userdiff.c +++ b/userdiff.c @@ -198,7 +198,7 @@ struct userdiff_driver *userdiff_find_by_path(const char *path) struct git_attr_check check; if (!attr) - attr = git_attr("diff", 4); + attr = git_attr("diff"); check.attr = attr; if (!path) diff --git a/ws.c b/ws.c index 760b574..c089338 100644 --- a/ws.c +++ b/ws.c @@ -64,7 +64,7 @@ static void setup_whitespace_attr_check(struct git_attr_check *check) static struct git_attr *attr_whitespace; if (!attr_whitespace) - attr_whitespace = git_attr("whitespace", 10); + attr_whitespace = git_attr("whitespace"); check[0].attr = attr_whitespace; } -- cgit v0.10.2-6-g49f6 From 00f8f97d30be7992c16bc466532cb591e00314bf Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Jan 2010 21:01:28 -0800 Subject: xdl_merge(): introduce xmparam_t for merge specific parameters So far we have only needed to be able to pass an option that is generic to xdiff family of functions to this function. Extend the interface so that we can give it merge specific parameters. Signed-off-by: Junio C Hamano diff --git a/builtin-merge-file.c b/builtin-merge-file.c index afd2ea7..11c3524 100644 --- a/builtin-merge-file.c +++ b/builtin-merge-file.c @@ -25,7 +25,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) const char *names[3] = { NULL, NULL, NULL }; mmfile_t mmfs[3]; mmbuffer_t result = {NULL, 0}; - xpparam_t xpp = {XDF_NEED_MINIMAL}; + xmparam_t xmp = {{XDF_NEED_MINIMAL}}; int ret = 0, i = 0, to_stdout = 0; int merge_level = XDL_MERGE_ZEALOUS_ALNUM; int merge_style = 0, quiet = 0; @@ -68,7 +68,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) } ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2], - &xpp, merge_level | merge_style, &result); + &xmp, merge_level | merge_style, &result); for (i = 0; i < 3; i++) free(mmfs[i].ptr); diff --git a/ll-merge.c b/ll-merge.c index f4b0a07..be2bf43 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -61,7 +61,7 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, mmfile_t *src2, const char *name2, int virtual_ancestor) { - xpparam_t xpp; + xmparam_t xmp; int style = 0; if (buffer_is_binary(orig->ptr, orig->size) || @@ -76,13 +76,13 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, virtual_ancestor); } - memset(&xpp, 0, sizeof(xpp)); + memset(&xmp, 0, sizeof(xmp)); if (git_xmerge_style >= 0) style = git_xmerge_style; return xdl_merge(orig, src1, name1, src2, name2, - &xpp, XDL_MERGE_ZEALOUS | style, + &xmp, XDL_MERGE_ZEALOUS | style, result); } diff --git a/merge-file.c b/merge-file.c index 3120a95..5c00c7e 100644 --- a/merge-file.c +++ b/merge-file.c @@ -27,12 +27,12 @@ static void free_mmfile(mmfile_t *f) static void *three_way_filemerge(mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size) { mmbuffer_t res; - xpparam_t xpp; + xmparam_t xmp; int merge_status; - memset(&xpp, 0, sizeof(xpp)); + memset(&xmp, 0, sizeof(xmp)); merge_status = xdl_merge(base, our, ".our", their, ".their", - &xpp, XDL_MERGE_ZEALOUS, &res); + &xmp, XDL_MERGE_ZEALOUS, &res); if (merge_status < 0) return NULL; diff --git a/rerere.c b/rerere.c index d92990a..adb0694 100644 --- a/rerere.c +++ b/rerere.c @@ -332,7 +332,7 @@ static int merge(const char *name, const char *path) int ret; mmfile_t cur, base, other; mmbuffer_t result = {NULL, 0}; - xpparam_t xpp = {XDF_NEED_MINIMAL}; + xmparam_t xmp = {{XDF_NEED_MINIMAL}}; if (handle_file(path, NULL, rerere_path(name, "thisimage")) < 0) return 1; @@ -342,7 +342,7 @@ static int merge(const char *name, const char *path) read_mmfile(&other, rerere_path(name, "postimage"))) return 1; ret = xdl_merge(&base, &cur, "", &other, "", - &xpp, XDL_MERGE_ZEALOUS, &result); + &xmp, XDL_MERGE_ZEALOUS, &result); if (!ret) { FILE *f = fopen(path, "w"); if (!f) diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index 4da052a..b265909 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -108,9 +108,13 @@ long xdl_mmfile_size(mmfile_t *mmf); int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb); +typedef struct s_xmparam { + xpparam_t xpp; +} xmparam_t; + int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, mmfile_t *mf2, const char *name2, - xpparam_t const *xpp, int level, mmbuffer_t *result); + xmparam_t const *xmp, int level, mmbuffer_t *result); #ifdef __cplusplus } diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c index 1cb65a9..5c37b4e 100644 --- a/xdiff/xmerge.c +++ b/xdiff/xmerge.c @@ -538,10 +538,11 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1, int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, mmfile_t *mf2, const char *name2, - xpparam_t const *xpp, int flags, mmbuffer_t *result) { + xmparam_t const *xmp, int flags, mmbuffer_t *result) { xdchange_t *xscr1, *xscr2; xdfenv_t xe1, xe2; int status; + xpparam_t const *xpp = &xmp->xpp; result->ptr = NULL; result->size = 0; -- cgit v0.10.2-6-g49f6 From 9914cf468941067b4f3deb9c69c11af3f5b45ccc Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Jan 2010 21:30:18 -0800 Subject: xdl_merge(): allow passing down marker_size in xmparam_t This allows the callers of xdl_merge() to pass marker_size (defaults to 7) in xmparam_t argument, to use conflict markers of non-default length. Signed-off-by: Junio C Hamano diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index b265909..22f3913 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -110,8 +110,11 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, typedef struct s_xmparam { xpparam_t xpp; + int marker_size; } xmparam_t; +#define DEFAULT_CONFLICT_MARKER_SIZE 7 + int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, mmfile_t *mf2, const char *name2, xmparam_t const *xmp, int level, mmbuffer_t *result); diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c index 5c37b4e..68c815f 100644 --- a/xdiff/xmerge.c +++ b/xdiff/xmerge.c @@ -145,13 +145,15 @@ static int xdl_orig_copy(xdfenv_t *xe, int i, int count, int add_nl, char *dest) static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1, xdfenv_t *xe2, const char *name2, int size, int i, int style, - xdmerge_t *m, char *dest) + xdmerge_t *m, char *dest, int marker_size) { - const int marker_size = 7; int marker1_size = (name1 ? strlen(name1) + 1 : 0); int marker2_size = (name2 ? strlen(name2) + 1 : 0); int j; + if (marker_size <= 0) + marker_size = DEFAULT_CONFLICT_MARKER_SIZE; + /* Before conflicting part */ size += xdl_recs_copy(xe1, i, m->i1 - i, 0, dest ? dest + size : NULL); @@ -214,14 +216,16 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1, static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1, xdfenv_t *xe2, const char *name2, - xdmerge_t *m, char *dest, int style) + xdmerge_t *m, char *dest, int style, + int marker_size) { int size, i; for (size = i = 0; m; m = m->next) { if (m->mode == 0) size = fill_conflict_hunk(xe1, name1, xe2, name2, - size, i, style, m, dest); + size, i, style, m, dest, + marker_size); else if (m->mode == 1) size += xdl_recs_copy(xe1, i, m->i1 + m->chg1 - i, 0, dest ? dest + size : NULL); @@ -386,8 +390,9 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m, */ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1, xdfenv_t *xe2, xdchange_t *xscr2, const char *name2, - int flags, xpparam_t const *xpp, mmbuffer_t *result) { + int flags, xmparam_t const *xmp, mmbuffer_t *result) { xdmerge_t *changes, *c; + xpparam_t const *xpp = &xmp->xpp; int i0, i1, i2, chg0, chg1, chg2; int level = flags & XDL_MERGE_LEVEL_MASK; int style = flags & XDL_MERGE_STYLE_MASK; @@ -522,8 +527,10 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1, } /* output */ if (result) { + int marker_size = xmp->marker_size; int size = xdl_fill_merge_buffer(xe1, name1, xe2, name2, - changes, NULL, style); + changes, NULL, style, + marker_size); result->ptr = xdl_malloc(size); if (!result->ptr) { xdl_cleanup_merge(changes); @@ -531,7 +538,7 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1, } result->size = size; xdl_fill_merge_buffer(xe1, name1, xe2, name2, changes, - result->ptr, style); + result->ptr, style, marker_size); } return xdl_cleanup_merge(changes); } @@ -575,7 +582,7 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, } else { status = xdl_do_merge(&xe1, xscr1, name1, &xe2, xscr2, name2, - flags, xpp, result); + flags, xmp, result); } xdl_free_script(xscr1); xdl_free_script(xscr2); -- cgit v0.10.2-6-g49f6 From 15b4f7a68d8c3c8ee28424415b203f61202d65d1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Jan 2010 21:45:40 -0800 Subject: merge-tree: use ll_merge() not xdl_merge() ll_merge() interface was designed to merge contents under git control while taking per-path attributes into account. Update the three-way merge implementation used by merge-tree to use it. Signed-off-by: Junio C Hamano diff --git a/merge-file.c b/merge-file.c index 5c00c7e..fd34d76 100644 --- a/merge-file.c +++ b/merge-file.c @@ -1,6 +1,7 @@ #include "cache.h" #include "run-command.h" #include "xdiff-interface.h" +#include "ll-merge.h" #include "blob.h" static int fill_mmfile_blob(mmfile_t *f, struct blob *obj) @@ -24,16 +25,13 @@ static void free_mmfile(mmfile_t *f) free(f->ptr); } -static void *three_way_filemerge(mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size) +static void *three_way_filemerge(const char *path, mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size) { - mmbuffer_t res; - xmparam_t xmp; int merge_status; + mmbuffer_t res; - memset(&xmp, 0, sizeof(xmp)); - merge_status = xdl_merge(base, our, ".our", their, ".their", - &xmp, XDL_MERGE_ZEALOUS, &res); - + merge_status = ll_merge(&res, path, base, + our, ".our", their, ".their", 0); if (merge_status < 0) return NULL; @@ -75,7 +73,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2) return xdi_diff(f1, f2, &xpp, &xecfg, &ecb); } -void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsigned long *size) +void *merge_file(const char *path, struct blob *base, struct blob *our, struct blob *their, unsigned long *size) { void *res = NULL; mmfile_t f1, f2, common; @@ -108,7 +106,7 @@ void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsign if (generate_common_file(&common, &f1, &f2) < 0) goto out_free_f2_f1; } - res = three_way_filemerge(&common, &f1, &f2, size); + res = three_way_filemerge(path, &common, &f1, &f2, size); free_mmfile(&common); out_free_f2_f1: free_mmfile(&f2); diff --git a/merge-tree.c b/merge-tree.c index f01e7c8..37b94d9 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -54,7 +54,7 @@ static const char *explanation(struct merge_list *entry) return "removed in remote"; } -extern void *merge_file(struct blob *, struct blob *, struct blob *, unsigned long *); +extern void *merge_file(const char *, struct blob *, struct blob *, struct blob *, unsigned long *); static void *result(struct merge_list *entry, unsigned long *size) { @@ -76,7 +76,7 @@ static void *result(struct merge_list *entry, unsigned long *size) their = NULL; if (entry) their = entry->blob; - return merge_file(base, our, their, size); + return merge_file(entry->path, base, our, their, size); } static void *origin(struct merge_list *entry, unsigned long *size) -- cgit v0.10.2-6-g49f6 From 88533f6d64ae898e5f94fa22fa9b5fd43fe3e16e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 15 Jan 2010 22:50:01 -0800 Subject: rerere: use ll_merge() instead of using xdl_merge() This allows us to pay attention to the attribute settings and custom merge driver the user sets up. Signed-off-by: Junio C Hamano diff --git a/rerere.c b/rerere.c index adb0694..5b8ebcb 100644 --- a/rerere.c +++ b/rerere.c @@ -1,7 +1,6 @@ #include "cache.h" #include "string-list.h" #include "rerere.h" -#include "xdiff/xdiff.h" #include "xdiff-interface.h" #include "dir.h" #include "resolve-undo.h" @@ -332,7 +331,6 @@ static int merge(const char *name, const char *path) int ret; mmfile_t cur, base, other; mmbuffer_t result = {NULL, 0}; - xmparam_t xmp = {{XDF_NEED_MINIMAL}}; if (handle_file(path, NULL, rerere_path(name, "thisimage")) < 0) return 1; @@ -341,8 +339,7 @@ static int merge(const char *name, const char *path) read_mmfile(&base, rerere_path(name, "preimage")) || read_mmfile(&other, rerere_path(name, "postimage"))) return 1; - ret = xdl_merge(&base, &cur, "", &other, "", - &xmp, XDL_MERGE_ZEALOUS, &result); + ret = ll_merge(&result, path, &base, &cur, "", &other, "", 0); if (!ret) { FILE *f = fopen(path, "w"); if (!f) -- cgit v0.10.2-6-g49f6 From 23a64c9e771e3caf19cf2ee9a32c8942ddde4a81 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 15 Jan 2010 22:37:32 -0800 Subject: conflict-marker-size: new attribute This can be specified to set the length of the conflict marker (usually 7) to a non-default value per path. Only the callers of ll_merge() that are aware of the per-path attributes are modified. Signed-off-by: Junio C Hamano diff --git a/ll-merge.c b/ll-merge.c index be2bf43..d682071 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -18,7 +18,8 @@ typedef int (*ll_merge_fn)(const struct ll_merge_driver *, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, - int virtual_ancestor); + int virtual_ancestor, + int marker_size); struct ll_merge_driver { const char *name; @@ -38,7 +39,7 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, - int virtual_ancestor) + int virtual_ancestor, int marker_size) { /* * The tentative merge result is "ours" for the final round, @@ -59,7 +60,7 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, - int virtual_ancestor) + int virtual_ancestor, int marker_size) { xmparam_t xmp; int style = 0; @@ -73,12 +74,14 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, path, orig, src1, name1, src2, name2, - virtual_ancestor); + virtual_ancestor, marker_size); } memset(&xmp, 0, sizeof(xmp)); if (git_xmerge_style >= 0) style = git_xmerge_style; + if (marker_size > 0) + xmp.marker_size = marker_size; return xdl_merge(orig, src1, name1, src2, name2, @@ -92,11 +95,10 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, - int virtual_ancestor) + int virtual_ancestor, int marker_size) { char *src, *dst; long size; - const int marker_size = 7; int status, saved_style; /* We have to force the RCS "merge" style */ @@ -104,7 +106,7 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused, git_xmerge_style = 0; status = ll_xdl_merge(drv_unused, result, path_unused, orig, src1, NULL, src2, NULL, - virtual_ancestor); + virtual_ancestor, marker_size); git_xmerge_style = saved_style; if (status <= 0) return status; @@ -165,14 +167,15 @@ static int ll_ext_merge(const struct ll_merge_driver *fn, mmfile_t *orig, mmfile_t *src1, const char *name1, mmfile_t *src2, const char *name2, - int virtual_ancestor) + int virtual_ancestor, int marker_size) { - char temp[3][50]; + char temp[4][50]; struct strbuf cmd = STRBUF_INIT; struct strbuf_expand_dict_entry dict[] = { { "O", temp[0] }, { "A", temp[1] }, { "B", temp[2] }, + { "L", temp[3] }, { NULL } }; const char *args[] = { "sh", "-c", NULL, NULL }; @@ -187,6 +190,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn, create_temp(orig, temp[0]); create_temp(src1, temp[1]); create_temp(src2, temp[2]); + sprintf(temp[3], "%d", marker_size); strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict); @@ -279,6 +283,7 @@ static int read_merge_config(const char *var, const char *value, void *cb) * %O - temporary file name for the merge base. * %A - temporary file name for our version. * %B - temporary file name for the other branches' version. + * %L - conflict marker length * * The external merge driver should write the results in the * file named by %A, and signal that it has done with zero exit @@ -339,16 +344,13 @@ static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr return &ll_merge_drv[LL_TEXT_MERGE]; } -static const char *git_path_check_merge(const char *path) +static int git_path_check_merge(const char *path, struct git_attr_check check[2]) { - static struct git_attr_check attr_merge_check; - - if (!attr_merge_check.attr) - attr_merge_check.attr = git_attr("merge"); - - if (git_checkattr(path, 1, &attr_merge_check)) - return NULL; - return attr_merge_check.value; + if (!check[0].attr) { + check[0].attr = git_attr("merge"); + check[1].attr = git_attr("conflict-marker-size"); + } + return git_checkattr(path, 2, check); } int ll_merge(mmbuffer_t *result_buf, @@ -358,16 +360,23 @@ int ll_merge(mmbuffer_t *result_buf, mmfile_t *theirs, const char *their_label, int virtual_ancestor) { - const char *ll_driver_name; + static struct git_attr_check check[2]; + const char *ll_driver_name = NULL; + int marker_size = DEFAULT_CONFLICT_MARKER_SIZE; const struct ll_merge_driver *driver; - ll_driver_name = git_path_check_merge(path); + if (!git_path_check_merge(path, check)) { + ll_driver_name = check[0].value; + if (check[1].value) { + marker_size = atoi(check[1].value); + if (marker_size <= 0) + marker_size = DEFAULT_CONFLICT_MARKER_SIZE; + } + } driver = find_ll_merge_driver(ll_driver_name); - if (virtual_ancestor && driver->recursive) driver = find_ll_merge_driver(driver->recursive); - return driver->fn(driver, result_buf, path, - ancestor, - ours, our_label, - theirs, their_label, virtual_ancestor); + return driver->fn(driver, result_buf, path, ancestor, + ours, our_label, theirs, their_label, + virtual_ancestor, marker_size); } -- cgit v0.10.2-6-g49f6 From 191f24171718e894cb5ba806bc45861ebac95e96 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Jan 2010 23:06:45 -0800 Subject: rerere: prepare for customizable conflict marker length This still uses the hardcoded conflict marker length of 7 but otherwise prepares the codepath to deal with customized marker length. Signed-off-by: Junio C Hamano diff --git a/rerere.c b/rerere.c index 5b8ebcb..5f332cb 100644 --- a/rerere.c +++ b/rerere.c @@ -98,6 +98,28 @@ static void rerere_io_putstr(const char *str, struct rerere_io *io) ferr_puts(str, io->output, &io->wrerror); } +static void rerere_io_putconflict(int ch, int size, struct rerere_io *io) +{ + char buf[64]; + + while (size) { + if (size < sizeof(buf) - 2) { + memset(buf, ch, size); + buf[size] = '\n'; + buf[size + 1] = '\0'; + size = 0; + } else { + int sz = sizeof(buf) - 1; + if (size <= sz) + sz -= (sz - size) + 1; + memset(buf, ch, sz); + buf[sz] = '\0'; + size -= sz; + } + rerere_io_putstr(buf, io); + } +} + static void rerere_io_putmem(const char *mem, size_t sz, struct rerere_io *io) { if (io->output) @@ -115,7 +137,17 @@ static int rerere_file_getline(struct strbuf *sb, struct rerere_io *io_) return strbuf_getwholeline(sb, io->input, '\n'); } -static int handle_path(unsigned char *sha1, struct rerere_io *io) +static int is_cmarker(char *buf, int marker_char, int marker_size, int want_sp) +{ + while (marker_size--) + if (*buf++ != marker_char) + return 0; + if (want_sp && *buf != ' ') + return 0; + return isspace(*buf); +} + +static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size) { git_SHA_CTX ctx; int hunk_no = 0; @@ -129,30 +161,30 @@ static int handle_path(unsigned char *sha1, struct rerere_io *io) git_SHA1_Init(&ctx); while (!io->getline(&buf, io)) { - if (!prefixcmp(buf.buf, "<<<<<<< ")) { + if (is_cmarker(buf.buf, '<', marker_size, 1)) { if (hunk != RR_CONTEXT) goto bad; hunk = RR_SIDE_1; - } else if (!prefixcmp(buf.buf, "|||||||") && isspace(buf.buf[7])) { + } else if (is_cmarker(buf.buf, '|', marker_size, 0)) { if (hunk != RR_SIDE_1) goto bad; hunk = RR_ORIGINAL; - } else if (!prefixcmp(buf.buf, "=======") && isspace(buf.buf[7])) { + } else if (is_cmarker(buf.buf, '=', marker_size, 0)) { if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL) goto bad; hunk = RR_SIDE_2; - } else if (!prefixcmp(buf.buf, ">>>>>>> ")) { + } else if (is_cmarker(buf.buf, '>', marker_size, 1)) { if (hunk != RR_SIDE_2) goto bad; if (strbuf_cmp(&one, &two) > 0) strbuf_swap(&one, &two); hunk_no++; hunk = RR_CONTEXT; - rerere_io_putstr("<<<<<<<\n", io); + rerere_io_putconflict('<', marker_size, io); rerere_io_putmem(one.buf, one.len, io); - rerere_io_putstr("=======\n", io); + rerere_io_putconflict('=', marker_size, io); rerere_io_putmem(two.buf, two.len, io); - rerere_io_putstr(">>>>>>>\n", io); + rerere_io_putconflict('>', marker_size, io); if (sha1) { git_SHA1_Update(&ctx, one.buf ? one.buf : "", one.len + 1); @@ -189,6 +221,7 @@ static int handle_file(const char *path, unsigned char *sha1, const char *output { int hunk_no = 0; struct rerere_io_file io; + int marker_size = 7; memset(&io, 0, sizeof(io)); io.io.getline = rerere_file_getline; @@ -205,7 +238,7 @@ static int handle_file(const char *path, unsigned char *sha1, const char *output } } - hunk_no = handle_path(sha1, (struct rerere_io *)&io); + hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size); fclose(io.input); if (io.io.wrerror) @@ -255,6 +288,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu struct cache_entry *ce; int pos, len, i, hunk_no; struct rerere_io_mem io; + int marker_size = 7; /* * Reproduce the conflicted merge in-core @@ -299,7 +333,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu strbuf_init(&io.input, 0); strbuf_attach(&io.input, result.ptr, result.size, result.size); - hunk_no = handle_path(sha1, (struct rerere_io *)&io); + hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size); strbuf_release(&io.input); if (io.io.output) fclose(io.io.output); -- cgit v0.10.2-6-g49f6 From 8588567c96490b8d236b1bc13f9bcb0dfa118efe Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Jan 2010 23:28:46 -0800 Subject: rerere: honor conflict-marker-size attribute Signed-off-by: Junio C Hamano diff --git a/ll-merge.c b/ll-merge.c index d682071..0dcaae0 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -380,3 +380,18 @@ int ll_merge(mmbuffer_t *result_buf, ours, our_label, theirs, their_label, virtual_ancestor, marker_size); } + +int ll_merge_marker_size(const char *path) +{ + static struct git_attr_check check; + int marker_size = DEFAULT_CONFLICT_MARKER_SIZE; + + if (!check.attr) + check.attr = git_attr("conflict-marker-size"); + if (!git_checkattr(path, 1, &check) && check.value) { + marker_size = atoi(check.value); + if (marker_size <= 0) + marker_size = DEFAULT_CONFLICT_MARKER_SIZE; + } + return marker_size; +} diff --git a/ll-merge.h b/ll-merge.h index 5388422..ff5d84a 100644 --- a/ll-merge.h +++ b/ll-merge.h @@ -12,4 +12,6 @@ int ll_merge(mmbuffer_t *result_buf, mmfile_t *theirs, const char *their_label, int virtual_ancestor); +int ll_merge_marker_size(const char *path); + #endif diff --git a/rerere.c b/rerere.c index 5f332cb..b988b46 100644 --- a/rerere.c +++ b/rerere.c @@ -5,6 +5,7 @@ #include "dir.h" #include "resolve-undo.h" #include "ll-merge.h" +#include "attr.h" /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */ static int rerere_enabled = -1; @@ -221,7 +222,7 @@ static int handle_file(const char *path, unsigned char *sha1, const char *output { int hunk_no = 0; struct rerere_io_file io; - int marker_size = 7; + int marker_size = ll_merge_marker_size(path); memset(&io, 0, sizeof(io)); io.io.getline = rerere_file_getline; @@ -288,7 +289,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu struct cache_entry *ce; int pos, len, i, hunk_no; struct rerere_io_mem io; - int marker_size = 7; + int marker_size = ll_merge_marker_size(path); /* * Reproduce the conflicted merge in-core -- cgit v0.10.2-6-g49f6