зеркало из https://github.com/microsoft/git.git
Merge branch 'jc/apply-epoch-patch'
* jc/apply-epoch-patch: apply: notice creation/removal patches produced by GNU diff
This commit is contained in:
Коммит
5762101602
|
@ -457,6 +457,76 @@ static int guess_p_value(const char *nameline)
|
|||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does the ---/+++ line has the POSIX timestamp after the last HT?
|
||||
* GNU diff puts epoch there to signal a creation/deletion event. Is
|
||||
* this such a timestamp?
|
||||
*/
|
||||
static int has_epoch_timestamp(const char *nameline)
|
||||
{
|
||||
/*
|
||||
* We are only interested in epoch timestamp; any non-zero
|
||||
* fraction cannot be one, hence "(\.0+)?" in the regexp below.
|
||||
* For the same reason, the date must be either 1969-12-31 or
|
||||
* 1970-01-01, and the seconds part must be "00".
|
||||
*/
|
||||
const char stamp_regexp[] =
|
||||
"^(1969-12-31|1970-01-01)"
|
||||
" "
|
||||
"[0-2][0-9]:[0-5][0-9]:00(\\.0+)?"
|
||||
" "
|
||||
"([-+][0-2][0-9][0-5][0-9])\n";
|
||||
const char *timestamp = NULL, *cp;
|
||||
static regex_t *stamp;
|
||||
regmatch_t m[10];
|
||||
int zoneoffset;
|
||||
int hourminute;
|
||||
int status;
|
||||
|
||||
for (cp = nameline; *cp != '\n'; cp++) {
|
||||
if (*cp == '\t')
|
||||
timestamp = cp + 1;
|
||||
}
|
||||
if (!timestamp)
|
||||
return 0;
|
||||
if (!stamp) {
|
||||
stamp = xmalloc(sizeof(*stamp));
|
||||
if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) {
|
||||
warning("Cannot prepare timestamp regexp %s",
|
||||
stamp_regexp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
status = regexec(stamp, timestamp, ARRAY_SIZE(m), m, 0);
|
||||
if (status) {
|
||||
if (status != REG_NOMATCH)
|
||||
warning("regexec returned %d for input: %s",
|
||||
status, timestamp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
zoneoffset = strtol(timestamp + m[3].rm_so + 1, NULL, 10);
|
||||
zoneoffset = (zoneoffset / 100) * 60 + (zoneoffset % 100);
|
||||
if (timestamp[m[3].rm_so] == '-')
|
||||
zoneoffset = -zoneoffset;
|
||||
|
||||
/*
|
||||
* YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
|
||||
* (west of GMT) or 1970-01-01 (east of GMT)
|
||||
*/
|
||||
if ((zoneoffset < 0 && memcmp(timestamp, "1969-12-31", 10)) ||
|
||||
(0 <= zoneoffset && memcmp(timestamp, "1970-01-01", 10)))
|
||||
return 0;
|
||||
|
||||
hourminute = (strtol(timestamp + 11, NULL, 10) * 60 +
|
||||
strtol(timestamp + 14, NULL, 10) -
|
||||
zoneoffset);
|
||||
|
||||
return ((zoneoffset < 0 && hourminute == 1440) ||
|
||||
(0 <= zoneoffset && !hourminute));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the name etc info from the ---/+++ lines of a traditional patch header
|
||||
*
|
||||
|
@ -493,7 +563,17 @@ static void parse_traditional_patch(const char *first, const char *second, struc
|
|||
} else {
|
||||
name = find_name(first, NULL, p_value, TERM_SPACE | TERM_TAB);
|
||||
name = find_name(second, name, p_value, TERM_SPACE | TERM_TAB);
|
||||
patch->old_name = patch->new_name = name;
|
||||
if (has_epoch_timestamp(first)) {
|
||||
patch->is_new = 1;
|
||||
patch->is_delete = 0;
|
||||
patch->new_name = name;
|
||||
} else if (has_epoch_timestamp(second)) {
|
||||
patch->is_new = 0;
|
||||
patch->is_delete = 1;
|
||||
patch->old_name = name;
|
||||
} else {
|
||||
patch->old_name = patch->new_name = name;
|
||||
}
|
||||
}
|
||||
if (!name)
|
||||
die("unable to find filename in patch at line %d", linenr);
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2009 Junio C Hamano
|
||||
|
||||
test_description='git-apply notices removal patches generated by GNU diff'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success setup '
|
||||
cat <<-EOF >c &&
|
||||
diff -ruN a/file b/file
|
||||
--- a/file TS0
|
||||
+++ b/file TS1
|
||||
@@ -0,0 +1 @@
|
||||
+something
|
||||
EOF
|
||||
|
||||
cat <<-EOF >d &&
|
||||
diff -ruN a/file b/file
|
||||
--- a/file TS0
|
||||
+++ b/file TS1
|
||||
@@ -1 +0,0 @@
|
||||
-something
|
||||
EOF
|
||||
|
||||
timeWest="1982-09-16 07:00:00.000000000 -0800" &&
|
||||
timeGMT="1982-09-16 15:00:00.000000000 +0000" &&
|
||||
timeEast="1982-09-17 00:00:00.000000000 +0900" &&
|
||||
|
||||
epocWest="1969-12-31 16:00:00.000000000 -0800" &&
|
||||
epocGMT="1970-01-01 00:00:00.000000000 +0000" &&
|
||||
epocEast="1970-01-01 09:00:00.000000000 +0900" &&
|
||||
|
||||
sed -e "s/TS0/$epocWest/" -e "s/TS1/$timeWest/" <c >createWest.patch &&
|
||||
sed -e "s/TS0/$epocEast/" -e "s/TS1/$timeEast/" <c >createEast.patch &&
|
||||
sed -e "s/TS0/$epocGMT/" -e "s/TS1/$timeGMT/" <c >createGMT.patch &&
|
||||
|
||||
sed -e "s/TS0/$timeWest/" -e "s/TS1/$timeWest/" <c >addWest.patch &&
|
||||
sed -e "s/TS0/$timeEast/" -e "s/TS1/$timeEast/" <c >addEast.patch &&
|
||||
sed -e "s/TS0/$timeGMT/" -e "s/TS1/$timeGMT/" <c >addGMT.patch &&
|
||||
|
||||
sed -e "s/TS0/$timeWest/" -e "s/TS1/$timeWest/" <d >emptyWest.patch &&
|
||||
sed -e "s/TS0/$timeEast/" -e "s/TS1/$timeEast/" <d >emptyEast.patch &&
|
||||
sed -e "s/TS0/$timeGMT/" -e "s/TS1/$timeGMT/" <d >emptyGMT.patch &&
|
||||
|
||||
sed -e "s/TS0/$timeWest/" -e "s/TS1/$epocWest/" <d >removeWest.patch &&
|
||||
sed -e "s/TS0/$timeEast/" -e "s/TS1/$epocEast/" <d >removeEast.patch &&
|
||||
sed -e "s/TS0/$timeGMT/" -e "s/TS1/$epocGMT/" <d >removeGMT.patch &&
|
||||
|
||||
echo something >something &&
|
||||
>empty
|
||||
'
|
||||
|
||||
for patch in *.patch
|
||||
do
|
||||
test_expect_success "test $patch" '
|
||||
rm -f file .git/index &&
|
||||
case "$patch" in
|
||||
create*)
|
||||
# must be able to create
|
||||
git apply --index $patch &&
|
||||
test_cmp file something &&
|
||||
# must notice the file is already there
|
||||
>file &&
|
||||
git add file &&
|
||||
test_must_fail git apply $patch
|
||||
;;
|
||||
add*)
|
||||
# must be able to create or patch
|
||||
git apply $patch &&
|
||||
test_cmp file something &&
|
||||
>file &&
|
||||
git apply $patch &&
|
||||
test_cmp file something
|
||||
;;
|
||||
empty*)
|
||||
# must leave an empty file
|
||||
cat something >file &&
|
||||
git add file &&
|
||||
git apply --index $patch &&
|
||||
test -f file &&
|
||||
test_cmp empty file
|
||||
;;
|
||||
remove*)
|
||||
# must remove the file
|
||||
cat something >file &&
|
||||
git add file &&
|
||||
git apply --index $patch &&
|
||||
! test -f file
|
||||
;;
|
||||
esac
|
||||
'
|
||||
done
|
||||
|
||||
test_done
|
Загрузка…
Ссылка в новой задаче