mirror of
https://github.com/git/git
synced 2024-08-27 19:49:21 +00:00
Merge branch 'bc/reread-attributes-during-rebase'
The "git am" based backend of "git rebase" ignored the result of updating ".gitattributes" done in one step when replaying subsequent steps. * bc/reread-attributes-during-rebase: am: reload .gitattributes after patching it path: add a function to check for path suffix
This commit is contained in:
commit
c8ada15456
11
apply.c
11
apply.c
|
@ -4643,6 +4643,7 @@ static int apply_patch(struct apply_state *state,
|
||||||
struct patch *list = NULL, **listp = &list;
|
struct patch *list = NULL, **listp = &list;
|
||||||
int skipped_patch = 0;
|
int skipped_patch = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
int flush_attributes = 0;
|
||||||
|
|
||||||
state->patch_input_file = filename;
|
state->patch_input_file = filename;
|
||||||
if (read_patch_file(&buf, fd) < 0)
|
if (read_patch_file(&buf, fd) < 0)
|
||||||
|
@ -4670,6 +4671,14 @@ static int apply_patch(struct apply_state *state,
|
||||||
patch_stats(state, patch);
|
patch_stats(state, patch);
|
||||||
*listp = patch;
|
*listp = patch;
|
||||||
listp = &patch->next;
|
listp = &patch->next;
|
||||||
|
|
||||||
|
if ((patch->new_name &&
|
||||||
|
ends_with_path_components(patch->new_name,
|
||||||
|
GITATTRIBUTES_FILE)) ||
|
||||||
|
(patch->old_name &&
|
||||||
|
ends_with_path_components(patch->old_name,
|
||||||
|
GITATTRIBUTES_FILE)))
|
||||||
|
flush_attributes = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (state->apply_verbosity > verbosity_normal)
|
if (state->apply_verbosity > verbosity_normal)
|
||||||
|
@ -4746,6 +4755,8 @@ static int apply_patch(struct apply_state *state,
|
||||||
if (state->summary && state->apply_verbosity > verbosity_silent)
|
if (state->summary && state->apply_verbosity > verbosity_silent)
|
||||||
summary_patch_list(list);
|
summary_patch_list(list);
|
||||||
|
|
||||||
|
if (flush_attributes)
|
||||||
|
reset_parsed_attributes();
|
||||||
end:
|
end:
|
||||||
free_patch_list(list);
|
free_patch_list(list);
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
|
|
21
convert.c
21
convert.c
|
@ -8,6 +8,7 @@
|
||||||
#include "pkt-line.h"
|
#include "pkt-line.h"
|
||||||
#include "sub-process.h"
|
#include "sub-process.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
#include "ll-merge.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* convert.c - convert a file when checking it out and checking it in.
|
* convert.c - convert a file when checking it out and checking it in.
|
||||||
|
@ -1293,10 +1294,11 @@ struct conv_attrs {
|
||||||
const char *working_tree_encoding; /* Supported encoding or default encoding if NULL */
|
const char *working_tree_encoding; /* Supported encoding or default encoding if NULL */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct attr_check *check;
|
||||||
|
|
||||||
static void convert_attrs(const struct index_state *istate,
|
static void convert_attrs(const struct index_state *istate,
|
||||||
struct conv_attrs *ca, const char *path)
|
struct conv_attrs *ca, const char *path)
|
||||||
{
|
{
|
||||||
static struct attr_check *check;
|
|
||||||
struct attr_check_item *ccheck = NULL;
|
struct attr_check_item *ccheck = NULL;
|
||||||
|
|
||||||
if (!check) {
|
if (!check) {
|
||||||
|
@ -1339,6 +1341,23 @@ static void convert_attrs(const struct index_state *istate,
|
||||||
ca->crlf_action = CRLF_AUTO_INPUT;
|
ca->crlf_action = CRLF_AUTO_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset_parsed_attributes(void)
|
||||||
|
{
|
||||||
|
struct convert_driver *drv, *next;
|
||||||
|
|
||||||
|
attr_check_free(check);
|
||||||
|
check = NULL;
|
||||||
|
reset_merge_attributes();
|
||||||
|
|
||||||
|
for (drv = user_convert; drv; drv = next) {
|
||||||
|
next = drv->next;
|
||||||
|
free((void *)drv->name);
|
||||||
|
free(drv);
|
||||||
|
}
|
||||||
|
user_convert = NULL;
|
||||||
|
user_convert_tail = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int would_convert_to_git_filter_fd(const struct index_state *istate, const char *path)
|
int would_convert_to_git_filter_fd(const struct index_state *istate, const char *path)
|
||||||
{
|
{
|
||||||
struct conv_attrs ca;
|
struct conv_attrs ca;
|
||||||
|
|
|
@ -94,6 +94,12 @@ void convert_to_git_filter_fd(const struct index_state *istate,
|
||||||
int would_convert_to_git_filter_fd(const struct index_state *istate,
|
int would_convert_to_git_filter_fd(const struct index_state *istate,
|
||||||
const char *path);
|
const char *path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the internal list of attributes used by convert_to_git and
|
||||||
|
* convert_to_working_tree.
|
||||||
|
*/
|
||||||
|
void reset_parsed_attributes(void);
|
||||||
|
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
*
|
*
|
||||||
* Streaming conversion support
|
* Streaming conversion support
|
||||||
|
|
19
ll-merge.c
19
ll-merge.c
|
@ -32,6 +32,20 @@ struct ll_merge_driver {
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct attr_check *merge_attributes;
|
||||||
|
static struct attr_check *load_merge_attributes(void)
|
||||||
|
{
|
||||||
|
if (!merge_attributes)
|
||||||
|
merge_attributes = attr_check_initl("merge", "conflict-marker-size", NULL);
|
||||||
|
return merge_attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_merge_attributes(void)
|
||||||
|
{
|
||||||
|
attr_check_free(merge_attributes);
|
||||||
|
merge_attributes = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Built-in low-levels
|
* Built-in low-levels
|
||||||
*/
|
*/
|
||||||
|
@ -354,7 +368,7 @@ int ll_merge(mmbuffer_t *result_buf,
|
||||||
struct index_state *istate,
|
struct index_state *istate,
|
||||||
const struct ll_merge_options *opts)
|
const struct ll_merge_options *opts)
|
||||||
{
|
{
|
||||||
static struct attr_check *check;
|
struct attr_check *check = load_merge_attributes();
|
||||||
static const struct ll_merge_options default_opts;
|
static const struct ll_merge_options default_opts;
|
||||||
const char *ll_driver_name = NULL;
|
const char *ll_driver_name = NULL;
|
||||||
int marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
|
int marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
|
||||||
|
@ -369,9 +383,6 @@ int ll_merge(mmbuffer_t *result_buf,
|
||||||
normalize_file(theirs, path, istate);
|
normalize_file(theirs, path, istate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check)
|
|
||||||
check = attr_check_initl("merge", "conflict-marker-size", NULL);
|
|
||||||
|
|
||||||
git_check_attr(istate, path, check);
|
git_check_attr(istate, path, check);
|
||||||
ll_driver_name = check->items[0].value;
|
ll_driver_name = check->items[0].value;
|
||||||
if (check->items[1].value) {
|
if (check->items[1].value) {
|
||||||
|
|
|
@ -26,5 +26,6 @@ int ll_merge(mmbuffer_t *result_buf,
|
||||||
const struct ll_merge_options *opts);
|
const struct ll_merge_options *opts);
|
||||||
|
|
||||||
int ll_merge_marker_size(struct index_state *istate, const char *path);
|
int ll_merge_marker_size(struct index_state *istate, const char *path);
|
||||||
|
void reset_merge_attributes(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
57
path.c
57
path.c
|
@ -1220,6 +1220,43 @@ static inline int chomp_trailing_dir_sep(const char *path, int len)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If path ends with suffix (complete path components), returns the offset of
|
||||||
|
* the last character in the path before the suffix (sans trailing directory
|
||||||
|
* separators), and -1 otherwise.
|
||||||
|
*/
|
||||||
|
static ssize_t stripped_path_suffix_offset(const char *path, const char *suffix)
|
||||||
|
{
|
||||||
|
int path_len = strlen(path), suffix_len = strlen(suffix);
|
||||||
|
|
||||||
|
while (suffix_len) {
|
||||||
|
if (!path_len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (is_dir_sep(path[path_len - 1])) {
|
||||||
|
if (!is_dir_sep(suffix[suffix_len - 1]))
|
||||||
|
return -1;
|
||||||
|
path_len = chomp_trailing_dir_sep(path, path_len);
|
||||||
|
suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
|
||||||
|
}
|
||||||
|
else if (path[--path_len] != suffix[--suffix_len])
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_len && !is_dir_sep(path[path_len - 1]))
|
||||||
|
return -1;
|
||||||
|
return chomp_trailing_dir_sep(path, path_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if the path ends with components, considering only complete path
|
||||||
|
* components, and false otherwise.
|
||||||
|
*/
|
||||||
|
int ends_with_path_components(const char *path, const char *components)
|
||||||
|
{
|
||||||
|
return stripped_path_suffix_offset(path, components) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If path ends with suffix (complete path components), returns the
|
* If path ends with suffix (complete path components), returns the
|
||||||
* part before suffix (sans trailing directory separators).
|
* part before suffix (sans trailing directory separators).
|
||||||
|
@ -1227,25 +1264,9 @@ static inline int chomp_trailing_dir_sep(const char *path, int len)
|
||||||
*/
|
*/
|
||||||
char *strip_path_suffix(const char *path, const char *suffix)
|
char *strip_path_suffix(const char *path, const char *suffix)
|
||||||
{
|
{
|
||||||
int path_len = strlen(path), suffix_len = strlen(suffix);
|
ssize_t offset = stripped_path_suffix_offset(path, suffix);
|
||||||
|
|
||||||
while (suffix_len) {
|
return offset == -1 ? NULL : xstrndup(path, offset);
|
||||||
if (!path_len)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (is_dir_sep(path[path_len - 1])) {
|
|
||||||
if (!is_dir_sep(suffix[suffix_len - 1]))
|
|
||||||
return NULL;
|
|
||||||
path_len = chomp_trailing_dir_sep(path, path_len);
|
|
||||||
suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
|
|
||||||
}
|
|
||||||
else if (path[--path_len] != suffix[--suffix_len])
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path_len && !is_dir_sep(path[path_len - 1]))
|
|
||||||
return NULL;
|
|
||||||
return xstrndup(path, chomp_trailing_dir_sep(path, path_len));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int daemon_avoid_alias(const char *p)
|
int daemon_avoid_alias(const char *p)
|
||||||
|
|
3
path.h
3
path.h
|
@ -193,4 +193,7 @@ const char *git_path_merge_head(struct repository *r);
|
||||||
const char *git_path_fetch_head(struct repository *r);
|
const char *git_path_fetch_head(struct repository *r);
|
||||||
const char *git_path_shallow(struct repository *r);
|
const char *git_path_shallow(struct repository *r);
|
||||||
|
|
||||||
|
|
||||||
|
int ends_with_path_components(const char *path, const char *components);
|
||||||
|
|
||||||
#endif /* PATH_H */
|
#endif /* PATH_H */
|
||||||
|
|
|
@ -301,6 +301,42 @@ test_expect_success 'rebase --am and --show-current-patch' '
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'rebase --am and .gitattributes' '
|
||||||
|
test_create_repo attributes &&
|
||||||
|
(
|
||||||
|
cd attributes &&
|
||||||
|
test_commit init &&
|
||||||
|
git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" &&
|
||||||
|
git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" &&
|
||||||
|
|
||||||
|
test_commit second &&
|
||||||
|
git checkout -b test HEAD^ &&
|
||||||
|
|
||||||
|
echo "*.txt filter=test" >.gitattributes &&
|
||||||
|
git add .gitattributes &&
|
||||||
|
test_commit third &&
|
||||||
|
|
||||||
|
echo "This text is smudged." >a.txt &&
|
||||||
|
git add a.txt &&
|
||||||
|
test_commit fourth &&
|
||||||
|
|
||||||
|
git checkout -b removal HEAD^ &&
|
||||||
|
git rm .gitattributes &&
|
||||||
|
git add -u &&
|
||||||
|
test_commit fifth &&
|
||||||
|
git cherry-pick test &&
|
||||||
|
|
||||||
|
git checkout test &&
|
||||||
|
git rebase master &&
|
||||||
|
grep "smudged" a.txt &&
|
||||||
|
|
||||||
|
git checkout removal &&
|
||||||
|
git reset --hard &&
|
||||||
|
git rebase master &&
|
||||||
|
grep "clean" a.txt
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'rebase--merge.sh and --show-current-patch' '
|
test_expect_success 'rebase--merge.sh and --show-current-patch' '
|
||||||
test_create_repo conflict-merge &&
|
test_create_repo conflict-merge &&
|
||||||
(
|
(
|
||||||
|
|
|
@ -1061,4 +1061,56 @@ test_expect_success 'am --quit keeps HEAD where it is' '
|
||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'am and .gitattibutes' '
|
||||||
|
test_create_repo attributes &&
|
||||||
|
(
|
||||||
|
cd attributes &&
|
||||||
|
test_commit init &&
|
||||||
|
git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" &&
|
||||||
|
git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" &&
|
||||||
|
|
||||||
|
test_commit second &&
|
||||||
|
git checkout -b test HEAD^ &&
|
||||||
|
|
||||||
|
echo "*.txt filter=test conflict-marker-size=10" >.gitattributes &&
|
||||||
|
git add .gitattributes &&
|
||||||
|
test_commit third &&
|
||||||
|
|
||||||
|
echo "This text is smudged." >a.txt &&
|
||||||
|
git add a.txt &&
|
||||||
|
test_commit fourth &&
|
||||||
|
|
||||||
|
git checkout -b removal HEAD^ &&
|
||||||
|
git rm .gitattributes &&
|
||||||
|
git add -u &&
|
||||||
|
test_commit fifth &&
|
||||||
|
git cherry-pick test &&
|
||||||
|
|
||||||
|
git checkout -b conflict third &&
|
||||||
|
echo "This text is different." >a.txt &&
|
||||||
|
git add a.txt &&
|
||||||
|
test_commit sixth &&
|
||||||
|
|
||||||
|
git checkout test &&
|
||||||
|
git format-patch --stdout master..HEAD >patches &&
|
||||||
|
git reset --hard master &&
|
||||||
|
git am patches &&
|
||||||
|
grep "smudged" a.txt &&
|
||||||
|
|
||||||
|
git checkout removal &&
|
||||||
|
git reset --hard &&
|
||||||
|
git format-patch --stdout master..HEAD >patches &&
|
||||||
|
git reset --hard master &&
|
||||||
|
git am patches &&
|
||||||
|
grep "clean" a.txt &&
|
||||||
|
|
||||||
|
git checkout conflict &&
|
||||||
|
git reset --hard &&
|
||||||
|
git format-patch --stdout master..HEAD >patches &&
|
||||||
|
git reset --hard fourth &&
|
||||||
|
test_must_fail git am -3 patches &&
|
||||||
|
grep "<<<<<<<<<<" a.txt
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
Loading…
Reference in a new issue