2 # TopGit - A different patch queue manager
3 # Copyright (C) Petr Baudis <pasky@suse.cz> 2008
4 # Copyright (C) Kyle J. McKay <mackyle@gmail.com> 2015
8 ## Set up all the tg machinery
21 # Don't do anything on a non-TopGit branch
22 if head_
=$
(git symbolic-ref
-q HEAD
); then
25 head_
="${head_#refs/heads/}"
26 git rev-parse
-q --verify "refs/$topbases/$head_" -- >/dev
/null ||
exit 0;;
41 _ls_line
="$(git ls-tree --long "$_tree" "$_file")" ||
42 die
"cannot ls tree for $_file"
45 die
"$_file is missing"
47 # check for type and size
52 # check file is of type blob (file)
53 [ "x$_type" = "xblob" ] ||
54 die
"$_file is not a file (i.e. not a 'blob')"
56 # check for positive size
57 [ -n "$_zerook" -o "$_size" -gt 0 ] ||
58 die
"$_file has empty size"
61 tree
=$
(git write-tree
) ||
62 die
"cannot write tree"
64 check_topfile
"$tree" ".topdeps" 1
65 check_topfile
"$tree" ".topmsg"
67 # Don't do anything more if neither .topdeps nor .topmsg is changing
71 headrev
="$(git rev-parse --quiet --verify HEAD -- || :)"
72 tab
="$(printf '\t.')" && tab
="${tab%?}"
73 prefix
="[A-Z][0-9]*$tab"
74 if [ -n "$headrev" ]; then
75 headtree
="$headrev^{tree}"
77 headtree
="$(: | git mktree)"
79 while read -r status fn
; do case "$fn" in
82 case "$status" in "A"*) mode
=create
; esac
85 case "$status" in "A"*) mode
=create
; esac
89 $(git diff-index --cached --name-status "$headtree" | LC_ALL=C grep -e "^$prefix\\.topdeps\$" -e "^$prefix\\.topmsg\$")
91 [ -n "$changedeps" -o -n "$changemsg" ] ||
exit 0
95 [ "$head_" != "$_dep" ] ||
96 die
"TopGit dependencies form a cycle: perpetrator is $_name"
101 # we only need to check newly added deps and for these if a path exists to the
103 git
diff --cached "$root_dir/.topdeps" |
105 BEGIN { in_hunk = 0; }
106 /^@@ / { in_hunk = 1; }
107 /^\+/ { if (in_hunk == 1) printf("%s\n", substr($0, 2)); }
108 /^[^@ +-]/ { in_hunk = 0; }
110 while read newly_added
; do
111 ref_exists
"refs/heads/$newly_added" ||
112 die
"invalid branch as dependent: $newly_added"
114 # check for self as dep
115 [ "$head_" != "$newly_added" ] ||
116 die
"cannot have myself as dependent"
118 # deps can be non-tgish but we can't run recurse_deps() on them
119 ref_exists
"refs/$topbases/$newly_added" ||
122 # recurse_deps uses dfs but takes the .topdeps from the tree,
123 # therefore no endless loop in the cycle-check
124 no_remotes
=1 recurse_deps check_cycle_name
"$newly_added"
128 # check for repetitions of deps
129 depdir
="$(get_temp tg-depdir -d)" ||
130 die
"cannot check for multiple occurrences of dependents"
131 cat_file
"$head_:.topdeps" -i |
133 [ ! -d "$depdir/$dep" ] ||
134 die
"multiple occurrences of the same dependent: $dep"
135 mkdir
-p "$depdir/$dep" ||
136 die
"cannot check for multiple occurrences of dependents"
141 # Only check .topdeps if it's been changed otherwise the assumption is it's been checked
142 [ -z "$changedeps" ] || check_topdeps
144 # If we are not sequestering TopGit files or the commit is changing only TopGit files we're done
145 [ -z "$tgnosequester" ] ||
exit 0
146 [ $
(( ${changedeps:-0} + ${changemsg:-0} )) -ne $
(git diff-index
--cached --name-only "$headtree" |
wc -l) ] ||
exit 0
148 # Sequester the TopGit-specific file changes into their own commit and notify the user we did so
149 tg_index
="$git_dir/tg-index"
150 if [ -n "$headrev" ]; then
151 GIT_INDEX_FILE
="$tg_index" git read-tree
"$headrev^{tree}"
153 GIT_INDEX_FILE
="$tg_index" git read-tree
--empty
155 prefix
="100[0-9][0-9][0-9] $octet20 0$tab"
157 printf '%s\n' "0 $nullsha$tab.topdeps"
158 printf '%s\n' "0 $nullsha$tab.topmsg"
159 git ls-files
--cached -s --full-name | LC_ALL
=C
grep -e "^$prefix\\.topdeps\$" -e "^$prefix\\.topmsg\$"
160 } | GIT_INDEX_FILE
="$tg_index" git update-index
--index-info
161 newtree
="$(GIT_INDEX_FILE="$tg_index" git write-tree)"
164 if [ -n "$changedeps" -a -n "$changemsg" ]; then
165 files
=".topdeps and .topmsg"
166 elif [ -n "$changedeps" ]; then
171 newcommit
="$(git commit-tree -m "tg
: $mode $files" ${headrev:+-p $headrev} "$newtree")"
172 git update-ref
-m "tg: sequester $files changes into their own preliminary commit" HEAD
"$newcommit"
173 warn
"sequestered $files changes into their own preliminary commit"
174 info
"run the same \`git commit\` command again to commit the remaining changes" >&2