-
Notifications
You must be signed in to change notification settings - Fork 0
/
cg-seek
executable file
·114 lines (98 loc) · 4.27 KB
/
cg-seek
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env bash
#
# Seek the working tree to a given commit
# Copyright (c) Petr Baudis, 2005
#
# Seeking will bring the working tree from its current 'HEAD' to a given
# commit. Note that it changes just the 'HEAD' of the working tree, not
# the branch it is corresponding to. It will return to the 'HEAD' of
# the appropriate branch if passed no arguments.
#
# Therefore, for a quick excursion to the past of the 'master' branch:
#
# $ cg-seek git-pasky-0.1
# $ cg-diff this master # will do the correct thing
# $ cg-seek # will restore what we had before
#
# For intuitiveness, specifying the branch name (`cg-seek master`) will do
# the right thing too. If you want to migrate your working tree to _another_
# branch, use `cg-clone` to create a new tree for the new branch, or
# `cg-switch` to also change your current tree to use the new branch.
#
# Note that during the time you are seeked out, commits, merges, and some
# other operations are blocked, since the next `cg-seek` or `cg-reset`
# invocation will happily wipe out their products silently. You can override
# this in the `cg-commit` command by passing it a '-f' parameter - this
# can be useful e.g. when you seeked to a commit which cannot be compiled
# and you want to commit a compilation fix, as long as you are aware that
# the commit of the fix will be rendered unreachable (you will be able to
# get back to it only if you remember its ID) at the moment you do next
# seek or a reset. If you want to save the commit, you can save it to
# a separate branch using `cg-switch -n`.
#
# Takes the target commit ID to seek to as an argument.
#
# NOTES
# -----
# The `cg-seek` command is meant only for temporary excursions to the commit
# history. If you want to permanently switch your branch to a different commit
# id (forgetting its current contents), you can use the `cg-switch` command:
#
# $ cg-switch -f -r COMMIT_ID CURRENT_HEAD_NAME
#
# Note that this command has some serious caveats! Please read the
# `cg-switch` documentation for details.
# Testsuite: Complete (t9300-seek)
USAGE="cg-seek [COMMIT_ID]"
_git_requires_root=1
. "${COGITO_LIB}"cg-Xlib || exit 1
dstcommit="${ARGS[0]}"
[ -s "$_git/blocked" ] && grep -vq '^seeked from ' "$_git/blocked" && die "action blocked: $(cat "$_git/blocked")"
curcommit="$(cg-object-id -c)" || exit 1
if [ "$dstcommit" ] && [ "$dstcommit" != "$_git_head" ]; then
seek_mode=away
[ -s "$_git/head-name" ] && [ "$(git-symbolic-ref HEAD)" != "refs/heads/cg-seek-point" ] &&
die "seeked away by some other tool, refusing to meddle (you can still use cg-seek without any arguments to unseek)"
exists_ref "refs/heads/$dstcommit" ] &&
warn "seeking to a branch head; this is not for permanent switching, please see cg-switch"
else
seek_mode=back
dstcommit="$(cg-object-id -c "$_git_head")" || exit 1
fi
dstcommit="$(cg-object-id -c "$dstcommit")" || exit 1
if [ "$curcommit" != "$dstcommit" ]; then
tree_timewarp --no-head-update "along" "please rollback" "$curcommit" "$dstcommit" || exit 1
fi
if [ "$seek_mode" = "away" ]; then
echo "$_git_head" >"$_git/head-name"
[ -s "$_git/blocked" ] || echo "seeked from $_git_head (some commands can be still forced)" >"$_git/blocked"
# We hold this in a temporary branch so that some of the core
# GIT tools (git checkout and git-fsck-objects) don't get confused.
git-update-ref "refs/heads/cg-seek-point" "$dstcommit"
git-symbolic-ref HEAD "refs/heads/cg-seek-point"
else # back
curref="$(git-symbolic-ref HEAD)"
# It may be that:
# (i) we are now on cg-seek-point, were cg-seek'd away in the past
# (ii) we are now on other seeky branch, were seeked by something
# else which kindly enough has set head-name
# (iii) we are now not seeked at all and the user has just did
# two cg-seeks without arguments in line or something
if [ "$curref" = "refs/heads/$_git_head" ]; then
# (iii)
if [ -s "$_git/head-name" ]; then
warn "you had stale head-name pointing at $_git_head (current branch) in your tree, removing"
fi
else
seekpt="$(get_ref "$curref")"
git-symbolic-ref HEAD "refs/heads/$_git_head"
if [ "$curref" != "refs/heads/cg-seek-point" ]; then
# (ii)
warn "dropping temporary head $curref pointing at $seekpt"
fi # else (i)
git-update-ref -d "$curref" "$seekpt"
fi
rm -f "$_git/head-name"
rm -f "$_git/blocked"
fi
echo "On commit $dstcommit"