#!/bin/sh

cacheexists() {
    [ -f .hg/tags.cache ] && echo "tag cache exists" || echo "no tag cache"
}

# XXX need to test that the tag cache works when we strip an old head
# and add a new one rooted off non-tip: i.e. node and rev of tip are the
# same, but stuff has changed behind tip.

echo "% setup"
mkdir t
cd t
hg init
cacheexists
hg id
cacheexists
echo a > a
hg add a
hg commit -m "test"
hg co
hg identify
cacheexists

echo "% create local tag with long name"
T=`hg identify --debug --id`
hg tag -l "This is a local tag with a really long name!"
hg tags
rm .hg/localtags

echo "% create a tag behind hg's back"
echo "$T first" > .hgtags
cat .hgtags
hg add .hgtags
hg commit -m "add tags"
hg tags
hg identify

# repeat with cold tag cache
echo "% identify with cold cache"
rm -f .hg/tags.cache
hg identify

# and again, but now unable to write tag cache
echo "% identify with unwritable cache"
rm -f .hg/tags.cache
chmod 555 .hg
hg identify
chmod 755 .hg

echo "% create a branch"
echo bb > a
hg status
hg identify
hg co first
hg id
hg -v id
hg status
echo 1 > b
hg add b
hg commit -m "branch"
hg id

echo "% merge the two heads"
hg merge 1
hg id
hg status

hg commit -m "merge"

echo "% create fake head, make sure tag not visible afterwards"
cp .hgtags tags
hg tag last
hg rm .hgtags
hg commit -m "remove"

mv tags .hgtags
hg add .hgtags
hg commit -m "readd"

hg tags

echo "% add invalid tags"
echo "spam" >> .hgtags
echo >> .hgtags
echo "foo bar" >> .hgtags
echo "$T invalid" | sed "s/..../a5a5/" >> .hg/localtags
echo "committing .hgtags:"
cat .hgtags 
hg commit -m "tags"

echo "% report tag parse error on other head"
hg up 3
echo 'x y' >> .hgtags
hg commit -m "head"

hg tags
hg tip

echo "% test tag precedence rules"
cd ..
hg init t2
cd t2
echo foo > foo
hg add foo
hg ci -m 'add foo'      # rev 0
hg tag bar              # rev 1
echo >> foo
hg ci -m 'change foo 1' # rev 2
hg up -C 1
hg tag -r 1 -f bar      # rev 3
hg up -C 1
echo >> foo
hg ci -m 'change foo 2' # rev 4
hg tags
hg tags         # repeat in case of cache effects

dumptags() {
    rev=$1
    echo "rev $rev: .hgtags:"
    hg cat -r$rev .hgtags
}

echo "% detailed dump of tag info"
echo "heads:"
hg heads -q             # expect 4, 3, 2
dumptags 2
dumptags 3
dumptags 4
echo ".hg/tags.cache:"
[ -f .hg/tags.cache ] && cat .hg/tags.cache || echo "no such file"

echo "% test tag removal"
hg tag --remove bar     # rev 5
hg tip -vp
hg tags
hg tags                 # again, try to expose cache bugs

echo '% remove nonexistent tag'
hg tag --remove foobar
hg tip

echo "% rollback undoes tag operation"
hg rollback             # destroy rev 5 (restore bar)
hg tags
hg tags

echo "% test tag rank"
cd ..
hg init t3
cd t3
echo foo > foo
hg add foo
hg ci -m 'add foo'       # rev 0
hg tag -f bar            # rev 1 bar -> 0
hg tag -f bar            # rev 2 bar -> 1
hg tag -fr 0 bar         # rev 3 bar -> 0
hg tag -fr 1 bar         # rev 4 bar -> 1
hg tag -fr 0 bar         # rev 5 bar -> 0
hg tags
hg co 3
echo barbar > foo
hg ci -m 'change foo'    # rev 6
hg tags

echo "% don't allow moving tag without -f"
hg tag -r 3 bar
hg tags

echo "% strip 1: expose an old head"
hg --config extensions.mq= strip 5 > /dev/null 2>&1
hg tags                  # partly stale cache
hg tags                  # up-to-date cache
echo "% strip 2: destroy whole branch, no old head exposed"
hg --config extensions.mq= strip 4 > /dev/null 2>&1 
hg tags                  # partly stale
rm -f .hg/tags.cache
hg tags                  # cold cache

echo "% test tag rank with 3 heads"
cd ..
hg init t4
cd t4
echo foo > foo
hg add
hg ci -m 'add foo'                 # rev 0
hg tag bar                         # rev 1 bar -> 0
hg tag -f bar                      # rev 2 bar -> 1
hg up -qC 0
hg tag -fr 2 bar                   # rev 3 bar -> 2
hg tags
hg up -qC 0
hg tag -m 'retag rev 0' -fr 0 bar  # rev 4 bar -> 0, but bar stays at 2
echo "% bar should still point to rev 2"
hg tags


echo "% remove local as global and global as local"
# test that removing global/local tags does not get confused when trying
# to remove a tag of type X which actually only exists as a type Y
cd ..
hg init t5
cd t5
echo foo > foo
hg add
hg ci -m 'add foo'                 # rev 0

hg tag -r 0 -l localtag
hg tag --remove localtag

hg tag -r 0 globaltag
hg tag --remove -l globaltag
hg tags -v
exit 0
