reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
#!/bin/sh
|
|
|
|
#
|
|
|
|
# Copyright (c) 2007 Junio C Hamano
|
|
|
|
#
|
|
|
|
|
|
|
|
test_description='Test prune and reflog expiration'
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
check_have () {
|
|
|
|
gaah= &&
|
|
|
|
for N in "$@"
|
|
|
|
do
|
|
|
|
eval "o=\$$N" && git cat-file -t $o || {
|
|
|
|
echo Gaah $N
|
|
|
|
gaah=$N
|
|
|
|
break
|
|
|
|
}
|
|
|
|
done &&
|
|
|
|
test -z "$gaah"
|
|
|
|
}
|
|
|
|
|
|
|
|
check_fsck () {
|
2018-11-10 05:16:15 +00:00
|
|
|
git fsck --full >fsck.output
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
case "$1" in
|
|
|
|
'')
|
2018-11-10 05:16:15 +00:00
|
|
|
test_must_be_empty fsck.output ;;
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
*)
|
2018-11-10 05:16:15 +00:00
|
|
|
test_i18ngrep "$1" fsck.output ;;
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
corrupt () {
|
|
|
|
aa=${1%??????????????????????????????????????} zz=${1#??}
|
|
|
|
mv .git/objects/$aa/$zz .git/$aa$zz
|
|
|
|
}
|
|
|
|
|
|
|
|
recover () {
|
|
|
|
aa=${1%??????????????????????????????????????} zz=${1#??}
|
|
|
|
mkdir -p .git/objects/$aa
|
|
|
|
mv .git/$aa$zz .git/objects/$aa/$zz
|
|
|
|
}
|
|
|
|
|
|
|
|
check_dont_have () {
|
|
|
|
gaah= &&
|
|
|
|
for N in "$@"
|
|
|
|
do
|
|
|
|
eval "o=\$$N"
|
|
|
|
git cat-file -t $o && {
|
|
|
|
echo Gaah $N
|
|
|
|
gaah=$N
|
|
|
|
break
|
|
|
|
}
|
|
|
|
done
|
|
|
|
test -z "$gaah"
|
|
|
|
}
|
|
|
|
|
|
|
|
test_expect_success setup '
|
|
|
|
mkdir -p A/B &&
|
|
|
|
echo rat >C &&
|
|
|
|
echo ox >A/D &&
|
|
|
|
echo tiger >A/B/E &&
|
|
|
|
git add . &&
|
|
|
|
|
|
|
|
test_tick && git commit -m rabbit &&
|
2015-12-22 15:05:48 +00:00
|
|
|
H=$(git rev-parse --verify HEAD) &&
|
|
|
|
A=$(git rev-parse --verify HEAD:A) &&
|
|
|
|
B=$(git rev-parse --verify HEAD:A/B) &&
|
|
|
|
C=$(git rev-parse --verify HEAD:C) &&
|
|
|
|
D=$(git rev-parse --verify HEAD:A/D) &&
|
|
|
|
E=$(git rev-parse --verify HEAD:A/B/E) &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
check_fsck &&
|
|
|
|
|
2009-02-28 20:12:57 +00:00
|
|
|
test_chmod +x C &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
git add C &&
|
|
|
|
test_tick && git commit -m dragon &&
|
2015-12-22 15:05:48 +00:00
|
|
|
L=$(git rev-parse --verify HEAD) &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
check_fsck &&
|
|
|
|
|
|
|
|
rm -f C A/B/E &&
|
|
|
|
echo snake >F &&
|
|
|
|
echo horse >A/G &&
|
|
|
|
git add F A/G &&
|
|
|
|
test_tick && git commit -a -m sheep &&
|
2015-12-22 15:05:48 +00:00
|
|
|
F=$(git rev-parse --verify HEAD:F) &&
|
|
|
|
G=$(git rev-parse --verify HEAD:A/G) &&
|
|
|
|
I=$(git rev-parse --verify HEAD:A) &&
|
|
|
|
J=$(git rev-parse --verify HEAD) &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
check_fsck &&
|
|
|
|
|
|
|
|
rm -f A/G &&
|
|
|
|
test_tick && git commit -a -m monkey &&
|
2015-12-22 15:05:48 +00:00
|
|
|
K=$(git rev-parse --verify HEAD) &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
check_fsck &&
|
|
|
|
|
|
|
|
check_have A B C D E F G H I J K L &&
|
|
|
|
|
2007-01-22 05:29:44 +00:00
|
|
|
git prune &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
|
|
|
|
check_have A B C D E F G H I J K L &&
|
|
|
|
|
|
|
|
check_fsck &&
|
|
|
|
|
2015-07-27 22:57:08 +00:00
|
|
|
git reflog refs/heads/master >output &&
|
|
|
|
test_line_count = 4 output
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success rewind '
|
|
|
|
test_tick && git reset --hard HEAD~2 &&
|
|
|
|
test -f C &&
|
|
|
|
test -f A/B/E &&
|
|
|
|
! test -f F &&
|
|
|
|
! test -f A/G &&
|
|
|
|
|
|
|
|
check_have A B C D E F G H I J K L &&
|
|
|
|
|
2007-01-22 05:29:44 +00:00
|
|
|
git prune &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
|
|
|
|
check_have A B C D E F G H I J K L &&
|
|
|
|
|
2015-07-27 22:57:08 +00:00
|
|
|
git reflog refs/heads/master >output &&
|
|
|
|
test_line_count = 5 output
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'corrupt and check' '
|
|
|
|
|
|
|
|
corrupt $F &&
|
|
|
|
check_fsck "missing blob $F"
|
|
|
|
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'reflog expire --dry-run should not touch reflog' '
|
|
|
|
|
|
|
|
git reflog expire --dry-run \
|
|
|
|
--expire=$(($test_tick - 10000)) \
|
|
|
|
--expire-unreachable=$(($test_tick - 10000)) \
|
|
|
|
--stale-fix \
|
|
|
|
--all &&
|
|
|
|
|
2015-07-27 22:57:08 +00:00
|
|
|
git reflog refs/heads/master >output &&
|
|
|
|
test_line_count = 5 output &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
|
|
|
|
check_fsck "missing blob $F"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'reflog expire' '
|
|
|
|
|
|
|
|
git reflog expire --verbose \
|
|
|
|
--expire=$(($test_tick - 10000)) \
|
|
|
|
--expire-unreachable=$(($test_tick - 10000)) \
|
|
|
|
--stale-fix \
|
|
|
|
--all &&
|
|
|
|
|
2015-07-27 22:57:08 +00:00
|
|
|
git reflog refs/heads/master >output &&
|
|
|
|
test_line_count = 2 output &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
|
|
|
|
check_fsck "dangling commit $K"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'prune and fsck' '
|
|
|
|
|
2007-01-22 05:29:44 +00:00
|
|
|
git prune &&
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
check_fsck &&
|
|
|
|
|
|
|
|
check_have A B C D E H L &&
|
|
|
|
check_dont_have F G I J K
|
|
|
|
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'recover and check' '
|
|
|
|
|
|
|
|
recover $F &&
|
|
|
|
check_fsck "dangling blob $F"
|
|
|
|
|
|
|
|
'
|
|
|
|
|
2008-08-11 06:21:25 +00:00
|
|
|
test_expect_success 'delete' '
|
2007-10-17 01:50:45 +00:00
|
|
|
echo 1 > C &&
|
|
|
|
test_tick &&
|
|
|
|
git commit -m rat C &&
|
|
|
|
|
|
|
|
echo 2 > C &&
|
|
|
|
test_tick &&
|
|
|
|
git commit -m ox C &&
|
|
|
|
|
|
|
|
echo 3 > C &&
|
|
|
|
test_tick &&
|
|
|
|
git commit -m tiger C &&
|
|
|
|
|
2010-10-31 01:46:54 +00:00
|
|
|
HEAD_entry_count=$(git reflog | wc -l) &&
|
|
|
|
master_entry_count=$(git reflog show master | wc -l) &&
|
2008-08-09 23:33:29 +00:00
|
|
|
|
|
|
|
test $HEAD_entry_count = 5 &&
|
|
|
|
test $master_entry_count = 5 &&
|
|
|
|
|
2007-10-17 01:50:45 +00:00
|
|
|
|
|
|
|
git reflog delete master@{1} &&
|
|
|
|
git reflog show master > output &&
|
2008-08-09 23:33:29 +00:00
|
|
|
test $(($master_entry_count - 1)) = $(wc -l < output) &&
|
|
|
|
test $HEAD_entry_count = $(git reflog | wc -l) &&
|
2007-10-17 01:50:45 +00:00
|
|
|
! grep ox < output &&
|
|
|
|
|
2010-10-31 01:46:54 +00:00
|
|
|
master_entry_count=$(wc -l < output) &&
|
2008-08-09 23:33:29 +00:00
|
|
|
|
|
|
|
git reflog delete HEAD@{1} &&
|
|
|
|
test $(($HEAD_entry_count -1)) = $(git reflog | wc -l) &&
|
|
|
|
test $master_entry_count = $(git reflog show master | wc -l) &&
|
|
|
|
|
2010-10-31 01:46:54 +00:00
|
|
|
HEAD_entry_count=$(git reflog | wc -l) &&
|
2008-08-09 23:33:29 +00:00
|
|
|
|
2007-10-17 01:50:45 +00:00
|
|
|
git reflog delete master@{07.04.2005.15:15:00.-0700} &&
|
|
|
|
git reflog show master > output &&
|
2008-08-09 23:33:29 +00:00
|
|
|
test $(($master_entry_count - 1)) = $(wc -l < output) &&
|
2007-10-17 01:50:45 +00:00
|
|
|
! grep dragon < output
|
2008-02-23 06:54:37 +00:00
|
|
|
|
|
|
|
'
|
|
|
|
|
2010-02-27 03:50:03 +00:00
|
|
|
test_expect_success 'rewind2' '
|
|
|
|
|
|
|
|
test_tick && git reset --hard HEAD~2 &&
|
2015-07-27 22:57:08 +00:00
|
|
|
git reflog refs/heads/master >output &&
|
|
|
|
test_line_count = 4 output
|
2010-02-27 03:50:03 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success '--expire=never' '
|
|
|
|
|
|
|
|
git reflog expire --verbose \
|
|
|
|
--expire=never \
|
|
|
|
--expire-unreachable=never \
|
|
|
|
--all &&
|
2015-07-27 22:57:08 +00:00
|
|
|
git reflog refs/heads/master >output &&
|
|
|
|
test_line_count = 4 output
|
2010-02-27 03:50:03 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'gc.reflogexpire=never' '
|
2019-03-15 15:59:55 +00:00
|
|
|
test_config gc.reflogexpire never &&
|
|
|
|
test_config gc.reflogexpireunreachable never &&
|
2010-02-27 03:50:03 +00:00
|
|
|
|
2019-03-28 16:14:33 +00:00
|
|
|
git reflog expire --verbose --all >output &&
|
|
|
|
test_line_count = 9 output &&
|
|
|
|
|
2015-07-27 22:57:08 +00:00
|
|
|
git reflog refs/heads/master >output &&
|
|
|
|
test_line_count = 4 output
|
2010-02-27 03:50:03 +00:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'gc.reflogexpire=false' '
|
2019-03-15 15:59:55 +00:00
|
|
|
test_config gc.reflogexpire false &&
|
|
|
|
test_config gc.reflogexpireunreachable false &&
|
2010-02-27 03:50:03 +00:00
|
|
|
|
|
|
|
git reflog expire --verbose --all &&
|
2015-07-27 22:57:08 +00:00
|
|
|
git reflog refs/heads/master >output &&
|
2019-03-15 15:59:55 +00:00
|
|
|
test_line_count = 4 output
|
2010-02-27 03:50:03 +00:00
|
|
|
|
|
|
|
'
|
|
|
|
|
2019-03-15 15:59:56 +00:00
|
|
|
test_expect_success 'git reflog expire unknown reference' '
|
|
|
|
test_config gc.reflogexpire never &&
|
|
|
|
test_config gc.reflogexpireunreachable never &&
|
|
|
|
|
|
|
|
test_must_fail git reflog expire master@{123} 2>stderr &&
|
|
|
|
test_i18ngrep "points nowhere" stderr &&
|
|
|
|
test_must_fail git reflog expire does-not-exist 2>stderr &&
|
|
|
|
test_i18ngrep "points nowhere" stderr
|
|
|
|
'
|
|
|
|
|
2014-05-06 22:45:53 +00:00
|
|
|
test_expect_success 'checkout should not delete log for packed ref' '
|
|
|
|
test $(git reflog master | wc -l) = 4 &&
|
|
|
|
git branch foo &&
|
|
|
|
git pack-refs --all &&
|
|
|
|
git checkout foo &&
|
|
|
|
test $(git reflog master | wc -l) = 4
|
|
|
|
'
|
|
|
|
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
test_expect_success 'stale dirs do not cause d/f conflicts (reflogs on)' '
|
2014-11-09 01:59:18 +00:00
|
|
|
test_when_finished "git branch -d one || git branch -d one/two" &&
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
|
2014-11-09 01:59:18 +00:00
|
|
|
git branch one/two master &&
|
|
|
|
echo "one/two@{0} branch: Created from master" >expect &&
|
|
|
|
git log -g --format="%gd %gs" one/two >actual &&
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
test_cmp expect actual &&
|
2014-11-09 01:59:18 +00:00
|
|
|
git branch -d one/two &&
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
|
2014-11-09 01:59:18 +00:00
|
|
|
# now logs/refs/heads/one is a stale directory, but
|
|
|
|
# we should move it out of the way to create "one" reflog
|
|
|
|
git branch one master &&
|
|
|
|
echo "one@{0} branch: Created from master" >expect &&
|
|
|
|
git log -g --format="%gd %gs" one >actual &&
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'stale dirs do not cause d/f conflicts (reflogs off)' '
|
2014-11-09 01:59:18 +00:00
|
|
|
test_when_finished "git branch -d one || git branch -d one/two" &&
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
|
2014-11-09 01:59:18 +00:00
|
|
|
git branch one/two master &&
|
|
|
|
echo "one/two@{0} branch: Created from master" >expect &&
|
|
|
|
git log -g --format="%gd %gs" one/two >actual &&
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
test_cmp expect actual &&
|
2014-11-09 01:59:18 +00:00
|
|
|
git branch -d one/two &&
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
|
2014-11-09 01:59:18 +00:00
|
|
|
# same as before, but we only create a reflog for "one" if
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
# it already exists, which it does not
|
2014-11-09 01:59:18 +00:00
|
|
|
git -c core.logallrefupdates=false branch one master &&
|
|
|
|
git log -g --format="%gd %gs" one >actual &&
|
tests: use 'test_must_be_empty' instead of 'test_cmp <empty> <out>'
Using 'test_must_be_empty' is shorter and more idiomatic than
>empty &&
test_cmp empty out
as it saves the creation of an empty file. Furthermore, sometimes the
expected empty file doesn't have such a descriptive name like 'empty',
and its creation is far away from the place where it's finally used
for comparison (e.g. in 't7600-merge.sh', where two expected empty
files are created in the 'setup' test, but are used only about 500
lines later).
These cases were found by instrumenting 'test_cmp' to error out the
test script when it's used to compare empty files, and then converted
manually.
Note that even after this patch there still remain a lot of cases
where we use 'test_cmp' to check empty files:
- Sometimes the expected output is not hard-coded in the test, but
'test_cmp' is used to ensure that two similar git commands produce
the same output, and that output happens to be empty, e.g. the
test 'submodule update --merge - ignores --merge for new
submodules' in 't7406-submodule-update.sh'.
- Repetitive common tasks, including preparing the expected results
and running 'test_cmp', are often extracted into a helper
function, and some of this helper's callsites expect no output.
- For the same reason as above, the whole 'test_expect_success'
block is within a helper function, e.g. in 't3070-wildmatch.sh'.
- Or 'test_cmp' is invoked in a loop, e.g. the test 'cvs update
(-p)' in 't9400-git-cvsserver-server.sh'.
Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-19 21:57:25 +00:00
|
|
|
test_must_be_empty actual
|
ignore stale directories when checking reflog existence
When we update a ref, we have two rules for whether or not
we actually update the reflog:
1. If the reflog already exists, we will always append to
it.
2. If log_all_ref_updates is set, we will create a new
reflog file if necessary.
We do the existence check by trying to open the reflog file,
either with or without O_CREAT (depending on log_all_ref_updates).
If it fails, then we check errno to see what happened.
If we were not using O_CREAT and we got ENOENT, the file
doesn't exist, and we return success (there isn't a reflog
already, and we were not told to make a new one).
If we get EISDIR, then there is likely a stale directory
that needs to be removed (e.g., there used to be "foo/bar",
it was deleted, and the directory "foo" was left. Now we
want to create the ref "foo"). If O_CREAT is set, then we
catch this case, try to remove the directory, and retry our
open. So far so good.
But if we get EISDIR and O_CREAT is not set, then we treat
this as any other error, which is not right. Like ENOENT,
EISDIR is an indication that we do not have a reflog, and we
should silently return success (we were not told to create
it). Instead, the current code reports this as an error, and
we fail to update the ref at all.
Note that this is relatively unlikely to happen, as you
would have to have had reflogs turned on, and then later
turned them off (it could also happen due to a bug in fetch,
but that was fixed in the previous commit). However, it's
quite easy to fix: we just need to treat EISDIR like ENOENT
for the non-O_CREAT case, and silently return (note that
this early return means we can also simplify the O_CREAT
case).
Our new tests cover both cases (O_CREAT and non-O_CREAT).
The first one already worked, of course.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-11-04 13:24:53 +00:00
|
|
|
'
|
|
|
|
|
for_each_reflog_ent_reverse: fix newlines on block boundaries
When we read a reflog file in reverse, we read whole chunks
of BUFSIZ bytes, then loop over the buffer, parsing any
lines we find. We find the beginning of each line by looking
for the newline from the previous line. If we don't find
one, we know that we are either at the beginning of
the file, or that we have to read another block.
In the latter case, we stuff away what we have into a
strbuf, read another block, and continue our parse. But we
missed one case here. If we did find a newline, and it is at
the beginning of the block, we must also stuff that newline
into the strbuf, as it belongs to the block we are about to
read.
The minimal fix here would be to add this special case to
the conditional that checks whether we found a newline.
But we can make the flow a little clearer by rearranging a
bit: we first handle lines that we are going to show, and
then at the end of each loop, stuff away any leftovers if
necessary. That lets us fold this special-case in with the
more common "we ended in the middle of a line" case.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-12-05 01:28:54 +00:00
|
|
|
# Triggering the bug detected by this test requires a newline to fall
|
|
|
|
# exactly BUFSIZ-1 bytes from the end of the file. We don't know
|
|
|
|
# what that value is, since it's platform dependent. However, if
|
|
|
|
# we choose some value N, we also catch any D which divides N evenly
|
|
|
|
# (since we will read backwards in chunks of D). So we choose 8K,
|
|
|
|
# which catches glibc (with an 8K BUFSIZ) and *BSD (1K).
|
|
|
|
#
|
|
|
|
# Each line is 114 characters, so we need 75 to still have a few before the
|
|
|
|
# last 8K. The 89-character padding on the final entry lines up our
|
|
|
|
# newline exactly.
|
|
|
|
test_expect_success 'parsing reverse reflogs at BUFSIZ boundaries' '
|
|
|
|
git checkout -b reflogskip &&
|
|
|
|
z38=00000000000000000000000000000000000000 &&
|
|
|
|
ident="abc <xyz> 0000000001 +0000" &&
|
|
|
|
for i in $(test_seq 1 75); do
|
|
|
|
printf "$z38%02d $z38%02d %s\t" $i $(($i+1)) "$ident" &&
|
|
|
|
if test $i = 75; then
|
|
|
|
for j in $(test_seq 1 89); do
|
|
|
|
printf X
|
|
|
|
done
|
|
|
|
else
|
|
|
|
printf X
|
|
|
|
fi &&
|
|
|
|
printf "\n"
|
|
|
|
done >.git/logs/refs/heads/reflogskip &&
|
|
|
|
git rev-parse reflogskip@{73} >actual &&
|
|
|
|
echo ${z38}03 >expect &&
|
|
|
|
test_cmp expect actual
|
|
|
|
'
|
|
|
|
|
2016-01-05 21:12:10 +00:00
|
|
|
test_expect_success 'no segfaults for reflog containing non-commit sha1s' '
|
|
|
|
git update-ref --create-reflog -m "Creating ref" \
|
|
|
|
refs/tests/tree-in-reflog HEAD &&
|
|
|
|
git update-ref -m "Forcing tree" refs/tests/tree-in-reflog HEAD^{tree} &&
|
|
|
|
git update-ref -m "Restoring to commit" refs/tests/tree-in-reflog HEAD &&
|
|
|
|
git reflog refs/tests/tree-in-reflog
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_failure 'reflog with non-commit entries displays all entries' '
|
|
|
|
git reflog refs/tests/tree-in-reflog >actual &&
|
|
|
|
test_line_count = 3 actual
|
|
|
|
'
|
|
|
|
|
2016-04-07 19:03:11 +00:00
|
|
|
test_expect_success 'reflog expire operates on symref not referrent' '
|
2018-06-22 09:23:59 +00:00
|
|
|
git branch --create-reflog the_symref &&
|
|
|
|
git branch --create-reflog referrent &&
|
2016-04-07 19:03:11 +00:00
|
|
|
git update-ref referrent HEAD &&
|
|
|
|
git symbolic-ref refs/heads/the_symref refs/heads/referrent &&
|
|
|
|
test_when_finished "rm -f .git/refs/heads/referrent.lock" &&
|
|
|
|
touch .git/refs/heads/referrent.lock &&
|
|
|
|
git reflog expire --expire=all the_symref
|
|
|
|
'
|
|
|
|
|
2016-06-03 20:42:35 +00:00
|
|
|
test_expect_success 'continue walking past root commits' '
|
|
|
|
git init orphanage &&
|
|
|
|
(
|
|
|
|
cd orphanage &&
|
|
|
|
cat >expect <<-\EOF &&
|
|
|
|
HEAD@{0} commit (initial): orphan2-1
|
|
|
|
HEAD@{1} commit: orphan1-2
|
|
|
|
HEAD@{2} commit (initial): orphan1-1
|
|
|
|
HEAD@{3} commit (initial): initial
|
|
|
|
EOF
|
|
|
|
test_commit initial &&
|
|
|
|
git checkout --orphan orphan1 &&
|
|
|
|
test_commit orphan1-1 &&
|
|
|
|
test_commit orphan1-2 &&
|
|
|
|
git checkout --orphan orphan2 &&
|
|
|
|
test_commit orphan2-1 &&
|
|
|
|
git log -g --format="%gd %gs" >actual &&
|
|
|
|
test_cmp expect actual
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
2018-10-21 08:08:59 +00:00
|
|
|
test_expect_success 'expire with multiple worktrees' '
|
|
|
|
git init main-wt &&
|
|
|
|
(
|
|
|
|
cd main-wt &&
|
|
|
|
test_tick &&
|
|
|
|
test_commit foo &&
|
|
|
|
git worktree add link-wt &&
|
|
|
|
test_tick &&
|
|
|
|
test_commit -C link-wt foobar &&
|
|
|
|
test_tick &&
|
|
|
|
git reflog expire --verbose --all --expire=$test_tick &&
|
|
|
|
test_must_be_empty .git/worktrees/link-wt/logs/HEAD
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
reflog expire --fix-stale
The logic in an earlier round to detect reflog entries that
point at a broken commit was not sufficient. Just like we do
not trust presense of a commit during pack transfer (we trust
only our refs), we should not trust a commit's presense, even if
the tree of that commit is complete.
A repository that had reflog enabled on some of the refs that
was rewound and then run git-repack or git-prune from older
versions of git can have reflog entries that point at a commit
that still exist but lack commits (or trees and blobs needed for
that commit) between it and some commit that is reachable from
one of the refs.
This revamps the logic -- the definition of "broken commit"
becomes: a commit that is not reachable from any of the refs and
there is a missing object among the commit, tree, or blob
objects reachable from it that is not reachable from any of the
refs. Entries in the reflog that refer to such a commit are
expired.
Since this computation involves traversing all the reachable
objects, i.e. it has the same cost as 'git prune', it is enabled
only when a new option --fix-stale. Fortunately, once this is
run, we should not have to ever worry about missing objects,
because the current prune and pack-objects know about reflogs
and protect objects referred by them.
Unfortunately, this will be absolutely necessary to help people
migrate to the newer prune and repack.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-06 10:16:19 +00:00
|
|
|
test_done
|