зеркало из https://github.com/microsoft/git.git
git-apply: guess correct -p<n> value for non-git patches.
This enhances the third point in the previous commit. When applying a non-git patch that begins like this: --- 2.6.orig/mm/slab.c +++ 2.6/mm/slab.c @@ -N,M +L,K @@@ ... and if you are in 'mm' subdirectory, we notice that -p2 is the right option to use to apply the patch in file slab.c in the current directory (i.e. mm/slab.c) The guess function also knows about this pattern, where you would need to use -p0 if applying from the top-level: --- mm/slab.c +++ mm/slab.c @@ -N,M +L,K @@@ ... Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Родитель
9987d7c58a
Коммит
3e8a5db966
|
@ -28,6 +28,7 @@ static int newfd = -1;
|
||||||
|
|
||||||
static int unidiff_zero;
|
static int unidiff_zero;
|
||||||
static int p_value = 1;
|
static int p_value = 1;
|
||||||
|
static int p_value_known;
|
||||||
static int check_index;
|
static int check_index;
|
||||||
static int write_index;
|
static int write_index;
|
||||||
static int cached;
|
static int cached;
|
||||||
|
@ -312,11 +313,54 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int count_slashes(const char *cp)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
while ((ch = *cp++))
|
||||||
|
if (ch == '/')
|
||||||
|
cnt++;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the string after "--- " or "+++ ", guess the appropriate
|
||||||
|
* p_value for the given patch.
|
||||||
|
*/
|
||||||
|
static int guess_p_value(const char *nameline)
|
||||||
|
{
|
||||||
|
char *name, *cp;
|
||||||
|
int val = -1;
|
||||||
|
|
||||||
|
if (is_dev_null(nameline))
|
||||||
|
return -1;
|
||||||
|
name = find_name(nameline, NULL, 0, TERM_SPACE | TERM_TAB);
|
||||||
|
if (!name)
|
||||||
|
return -1;
|
||||||
|
cp = strchr(name, '/');
|
||||||
|
if (!cp)
|
||||||
|
val = 0;
|
||||||
|
else if (prefix) {
|
||||||
|
/*
|
||||||
|
* Does it begin with "a/$our-prefix" and such? Then this is
|
||||||
|
* very likely to apply to our directory.
|
||||||
|
*/
|
||||||
|
if (!strncmp(name, prefix, prefix_length))
|
||||||
|
val = count_slashes(prefix);
|
||||||
|
else {
|
||||||
|
cp++;
|
||||||
|
if (!strncmp(cp, prefix, prefix_length))
|
||||||
|
val = count_slashes(prefix) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(name);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the name etc info from the --/+++ lines of a traditional patch header
|
* Get the name etc info from the --/+++ lines of a traditional patch header
|
||||||
*
|
*
|
||||||
* NOTE! This hardcodes "-p1" behaviour in filename detection.
|
|
||||||
*
|
|
||||||
* FIXME! The end-of-filename heuristics are kind of screwy. For existing
|
* FIXME! The end-of-filename heuristics are kind of screwy. For existing
|
||||||
* files, we can happily check the index for a match, but for creating a
|
* files, we can happily check the index for a match, but for creating a
|
||||||
* new file we should try to match whatever "patch" does. I have no idea.
|
* new file we should try to match whatever "patch" does. I have no idea.
|
||||||
|
@ -327,6 +371,16 @@ static void parse_traditional_patch(const char *first, const char *second, struc
|
||||||
|
|
||||||
first += 4; /* skip "--- " */
|
first += 4; /* skip "--- " */
|
||||||
second += 4; /* skip "+++ " */
|
second += 4; /* skip "+++ " */
|
||||||
|
if (!p_value_known) {
|
||||||
|
int p, q;
|
||||||
|
p = guess_p_value(first);
|
||||||
|
q = guess_p_value(second);
|
||||||
|
if (p < 0) p = q;
|
||||||
|
if (0 <= p && p == q) {
|
||||||
|
p_value = p;
|
||||||
|
p_value_known = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (is_dev_null(first)) {
|
if (is_dev_null(first)) {
|
||||||
patch->is_new = 1;
|
patch->is_new = 1;
|
||||||
patch->is_delete = 0;
|
patch->is_delete = 0;
|
||||||
|
@ -2656,6 +2710,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||||
}
|
}
|
||||||
if (!strncmp(arg, "-p", 2)) {
|
if (!strncmp(arg, "-p", 2)) {
|
||||||
p_value = atoi(arg + 2);
|
p_value = atoi(arg + 2);
|
||||||
|
p_value_known = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--no-add")) {
|
if (!strcmp(arg, "--no-add")) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ test_expect_success setup '
|
||||||
'
|
'
|
||||||
|
|
||||||
# Also handcraft GNU diff output; note this has trailing whitespace.
|
# Also handcraft GNU diff output; note this has trailing whitespace.
|
||||||
cat >gpatch.file <<\EOF
|
cat >gpatch.file <<\EOF &&
|
||||||
--- file1 2007-02-21 01:04:24.000000000 -0800
|
--- file1 2007-02-21 01:04:24.000000000 -0800
|
||||||
+++ file1+ 2007-02-21 01:07:44.000000000 -0800
|
+++ file1+ 2007-02-21 01:07:44.000000000 -0800
|
||||||
@@ -1 +1 @@
|
@@ -1 +1 @@
|
||||||
|
@ -27,6 +27,12 @@ cat >gpatch.file <<\EOF
|
||||||
+B
|
+B
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
sed -e 's|file1|sub/&|' gpatch.file >gpatch-sub.file &&
|
||||||
|
sed -e '
|
||||||
|
/^--- /s|file1|a/sub/&|
|
||||||
|
/^+++ /s|file1|b/sub/&|
|
||||||
|
' gpatch.file >gpatch-ab-sub.file &&
|
||||||
|
|
||||||
test_expect_success 'apply --whitespace=strip' '
|
test_expect_success 'apply --whitespace=strip' '
|
||||||
|
|
||||||
rm -f sub/file1 &&
|
rm -f sub/file1 &&
|
||||||
|
@ -124,7 +130,53 @@ test_expect_success 'same in subdir but with traditional patch input' '
|
||||||
git update-index --refresh &&
|
git update-index --refresh &&
|
||||||
|
|
||||||
cd sub &&
|
cd sub &&
|
||||||
git apply -p0 ../gpatch.file &&
|
git apply ../gpatch.file &&
|
||||||
|
if grep " " file1
|
||||||
|
then
|
||||||
|
echo "Eh?"
|
||||||
|
false
|
||||||
|
elif grep B file1
|
||||||
|
then
|
||||||
|
echo Happy
|
||||||
|
else
|
||||||
|
echo "Huh?"
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'same but with traditional patch input of depth 1' '
|
||||||
|
|
||||||
|
cd "$D" &&
|
||||||
|
git config apply.whitespace strip &&
|
||||||
|
rm -f sub/file1 &&
|
||||||
|
cp saved sub/file1 &&
|
||||||
|
git update-index --refresh &&
|
||||||
|
|
||||||
|
cd sub &&
|
||||||
|
git apply ../gpatch-sub.file &&
|
||||||
|
if grep " " file1
|
||||||
|
then
|
||||||
|
echo "Eh?"
|
||||||
|
false
|
||||||
|
elif grep B file1
|
||||||
|
then
|
||||||
|
echo Happy
|
||||||
|
else
|
||||||
|
echo "Huh?"
|
||||||
|
false
|
||||||
|
fi
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'same but with traditional patch input of depth 2' '
|
||||||
|
|
||||||
|
cd "$D" &&
|
||||||
|
git config apply.whitespace strip &&
|
||||||
|
rm -f sub/file1 &&
|
||||||
|
cp saved sub/file1 &&
|
||||||
|
git update-index --refresh &&
|
||||||
|
|
||||||
|
cd sub &&
|
||||||
|
git apply ../gpatch-ab-sub.file &&
|
||||||
if grep " " file1
|
if grep " " file1
|
||||||
then
|
then
|
||||||
echo "Eh?"
|
echo "Eh?"
|
||||||
|
|
Загрузка…
Ссылка в новой задаче