* [PATCH 1/8] git_attr(): fix function signature
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
@ 2010-01-17 9:38 ` Junio C Hamano
2010-01-17 9:38 ` [PATCH 2/8] xdl_merge(): introduce xmparam_t for merge specific parameters Junio C Hamano
` (7 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 9:38 UTC (permalink / raw)
To: git
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 <gitster@pobox.com>
---
archive.c | 4 ++--
attr.c | 11 ++++++++---
attr.h | 2 +-
builtin-check-attr.c | 2 +-
builtin-pack-objects.c | 2 +-
convert.c | 6 +++---
ll-merge.c | 2 +-
userdiff.c | 2 +-
ws.c | 2 +-
9 files changed, 19 insertions(+), 14 deletions(-)
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;
}
--
1.6.6.405.g80ed6.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/8] xdl_merge(): introduce xmparam_t for merge specific parameters
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
2010-01-17 9:38 ` [PATCH 1/8] git_attr(): fix function signature Junio C Hamano
@ 2010-01-17 9:38 ` Junio C Hamano
2010-01-17 9:38 ` [PATCH 3/8] xdl_merge(): allow passing down marker_size in xmparam_t Junio C Hamano
` (6 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 9:38 UTC (permalink / raw)
To: git
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 <gitster@pobox.com>
---
builtin-merge-file.c | 4 ++--
ll-merge.c | 6 +++---
merge-file.c | 6 +++---
rerere.c | 4 ++--
xdiff/xdiff.h | 6 +++++-
xdiff/xmerge.c | 3 ++-
6 files changed, 17 insertions(+), 12 deletions(-)
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;
--
1.6.6.405.g80ed6.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/8] xdl_merge(): allow passing down marker_size in xmparam_t
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
2010-01-17 9:38 ` [PATCH 1/8] git_attr(): fix function signature Junio C Hamano
2010-01-17 9:38 ` [PATCH 2/8] xdl_merge(): introduce xmparam_t for merge specific parameters Junio C Hamano
@ 2010-01-17 9:38 ` Junio C Hamano
2010-01-17 9:39 ` [PATCH 4/8] merge-tree: use ll_merge() not xdl_merge() Junio C Hamano
` (5 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 9:38 UTC (permalink / raw)
To: git
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 <gitster@pobox.com>
---
xdiff/xdiff.h | 3 +++
xdiff/xmerge.c | 23 +++++++++++++++--------
2 files changed, 18 insertions(+), 8 deletions(-)
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);
--
1.6.6.405.g80ed6.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/8] merge-tree: use ll_merge() not xdl_merge()
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
` (2 preceding siblings ...)
2010-01-17 9:38 ` [PATCH 3/8] xdl_merge(): allow passing down marker_size in xmparam_t Junio C Hamano
@ 2010-01-17 9:39 ` Junio C Hamano
2010-01-17 9:39 ` [PATCH 5/8] rerere: use ll_merge() instead of using xdl_merge() Junio C Hamano
` (4 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 9:39 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
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 <gitster@pobox.com>
---
merge-file.c | 16 +++++++---------
merge-tree.c | 4 ++--
2 files changed, 9 insertions(+), 11 deletions(-)
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)
--
1.6.6.405.g80ed6.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/8] rerere: use ll_merge() instead of using xdl_merge()
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
` (3 preceding siblings ...)
2010-01-17 9:39 ` [PATCH 4/8] merge-tree: use ll_merge() not xdl_merge() Junio C Hamano
@ 2010-01-17 9:39 ` Junio C Hamano
2010-01-17 11:52 ` Johannes Sixt
2010-01-17 9:39 ` [PATCH 6/8] conflict-marker-size: new attribute Junio C Hamano
` (3 subsequent siblings)
8 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 9:39 UTC (permalink / raw)
To: git; +Cc: Johannes Sixt
This allows us to pay attention to the attribute settings and custom
merge driver the user sets up.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
rerere.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
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)
--
1.6.6.405.g80ed6.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 5/8] rerere: use ll_merge() instead of using xdl_merge()
2010-01-17 9:39 ` [PATCH 5/8] rerere: use ll_merge() instead of using xdl_merge() Junio C Hamano
@ 2010-01-17 11:52 ` Johannes Sixt
2010-01-17 19:01 ` Junio C Hamano
0 siblings, 1 reply; 13+ messages in thread
From: Johannes Sixt @ 2010-01-17 11:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Sonntag, 17. Januar 2010, Junio C Hamano wrote:
> This allows us to pay attention to the attribute settings and custom
> merge driver the user sets up.
I do not think that this change is necessary; I even think that it is wrong,
in particular, custom merge drivers should *not* be used anymore.
The code path is about merging the changes between preimage and postimage into
a file that has conflict markers (thisimage). At the time when this happens,
all three images have already been processed by the custom merge driver.
Consider this preimage:
<foo><bar>
<<<<<<<
</bar>
=======
<baz>
text
</baz></bar>
>>>>>>>
<more text="here" />
</foo>
and a custom XML merge driver. With your change, you expect that the merge
driver knows how to treat syntactically incorrect XML (the "<<<<<<<"
and ">>>>>>>").
Of course, without this change, we do expect that the postimage has
practically everything outside the conflict markers unchanged[*], otherwise
the ll_merge() will fail.
But so would a custom XML driver that does not know how to read conflict
markers.
[*] Which is perhaps an assumption that is easily violated. For example, the
XML editor used to resolve the conflict could have inserted line-breaks at
completely different spots than in the conflicted preimage.
-- Hannes
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 5/8] rerere: use ll_merge() instead of using xdl_merge()
2010-01-17 11:52 ` Johannes Sixt
@ 2010-01-17 19:01 ` Junio C Hamano
2010-01-17 20:40 ` Johannes Sixt
0 siblings, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 19:01 UTC (permalink / raw)
To: Johannes Sixt; +Cc: git
Johannes Sixt <j6t@kdbg.org> writes:
> On Sonntag, 17. Januar 2010, Junio C Hamano wrote:
>> This allows us to pay attention to the attribute settings and custom
>> merge driver the user sets up.
>
> I do not think that this change is necessary; I even think that it is wrong,
> in particular, custom merge drivers should *not* be used anymore.
You are right in that nothing is strictly necessary as long as there are
other ways to do so. This does not have to be how the issue is solved,
but I found this to be one and the most natural way to allow rerere to pay
attention to per-path conflict marker length attribute.
Contents that you would want to use custom merge drivers would not benefit
from the current rerere that uses the default textual merge. In your
customized XML merge editor example, the merged contents have irrelevant
line breaks on either side of the merge that break textual merge (and that
is the reason you are using a custom XML aware merge script to begin with).
So I didn't think using ll_merge() makes things worse, and that was the
reason why I did it this way.
But I admit I didn't think things through (and that is why your name was
on the Cc: line). If you really want to forbid custom merge drivers, I
think we can add an option to ll_merge() to specify which attribute to
ignore, and force the default textual merge in the codepath, or we can go
back to the xdl_merge() but pass a custom conflict marker length in
xmparam_t, as a follow-up fix.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 5/8] rerere: use ll_merge() instead of using xdl_merge()
2010-01-17 19:01 ` Junio C Hamano
@ 2010-01-17 20:40 ` Johannes Sixt
0 siblings, 0 replies; 13+ messages in thread
From: Johannes Sixt @ 2010-01-17 20:40 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Sonntag, 17. Januar 2010, Junio C Hamano wrote:
> So I didn't think using ll_merge() makes things worse, and that was the
> reason why I did it this way.
Thinking a bit more about it, the problematic point is not that a custom merge
driver is used, but it is the way how conflicts are marked. For example, it
seems a bit strange that an XML merge driver would mark-up conflicts using
<<<<<<< and >>>>>>> in random points of XML text, when it knows that the
result would be invalid XML (and subsequently an XML editor could fail to
parse the result). It would be more apropriate when it used a different way
to mark conflicts.
The conclusion is that your approach goes in the right direction. But since
the result depends on the traditional conflict markers, it keeps rerere tied
to the standard text merge driver. The capability that rerere will use custom
merge drivers is of little use (unless the merge driver uses standard
conflict markers); that it allows attributes for the standard text merge, is,
of course, a plus.
-- Hannes
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 6/8] conflict-marker-size: new attribute
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
` (4 preceding siblings ...)
2010-01-17 9:39 ` [PATCH 5/8] rerere: use ll_merge() instead of using xdl_merge() Junio C Hamano
@ 2010-01-17 9:39 ` Junio C Hamano
2010-01-17 9:39 ` [PATCH 7/8] rerere: prepare for customizable conflict marker length Junio C Hamano
` (2 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 9:39 UTC (permalink / raw)
To: git
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 <gitster@pobox.com>
---
ll-merge.c | 59 ++++++++++++++++++++++++++++++++++-------------------------
1 files changed, 34 insertions(+), 25 deletions(-)
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);
}
--
1.6.6.405.g80ed6.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 7/8] rerere: prepare for customizable conflict marker length
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
` (5 preceding siblings ...)
2010-01-17 9:39 ` [PATCH 6/8] conflict-marker-size: new attribute Junio C Hamano
@ 2010-01-17 9:39 ` Junio C Hamano
2010-01-17 9:39 ` [PATCH 8/8] rerere: honor conflict-marker-size attribute Junio C Hamano
2010-01-17 10:07 ` [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
8 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 9:39 UTC (permalink / raw)
To: git
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 <gitster@pobox.com>
---
rerere.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/rerere.c b/rerere.c
index 5b8ebcb..d4d1507 100644
--- a/rerere.c
+++ b/rerere.c
@@ -98,6 +98,25 @@ 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 + 2 < sizeof(buf)) {
+ memset(buf, ch, size);
+ buf[size] = '\n';
+ buf[size + 1] = '\0';
+ size = 0;
+ } else {
+ memset(buf, ch, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ size -= sizeof(buf) - 1;
+ }
+ 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 +134,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 +158,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 +218,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 +235,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 +285,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 +330,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);
--
1.6.6.405.g80ed6.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 8/8] rerere: honor conflict-marker-size attribute
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
` (6 preceding siblings ...)
2010-01-17 9:39 ` [PATCH 7/8] rerere: prepare for customizable conflict marker length Junio C Hamano
@ 2010-01-17 9:39 ` Junio C Hamano
2010-01-17 10:07 ` [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
8 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 9:39 UTC (permalink / raw)
To: git
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
ll-merge.c | 15 +++++++++++++++
ll-merge.h | 2 ++
rerere.c | 5 +++--
3 files changed, 20 insertions(+), 2 deletions(-)
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 d4d1507..2a2bd23 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;
@@ -218,7 +219,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;
@@ -285,7 +286,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
--
1.6.6.405.g80ed6.dirty
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt
2010-01-17 9:38 [PATCH 0/8] Rescuing repeated merge of Documentation/git-merge.txt Junio C Hamano
` (7 preceding siblings ...)
2010-01-17 9:39 ` [PATCH 8/8] rerere: honor conflict-marker-size attribute Junio C Hamano
@ 2010-01-17 10:07 ` Junio C Hamano
8 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2010-01-17 10:07 UTC (permalink / raw)
To: git
7th one of the series has a minor nit; I fixed it up before pushing it out
to 'pu'.
^ permalink raw reply [flat|nested] 13+ messages in thread